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 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_port.h"
31 : #include "gdal.h"
32 : #include "gdal_priv.h"
33 :
34 : #include <climits>
35 : #include <cstdarg>
36 : #include <cstdio>
37 : #include <cstdlib>
38 : #include <cstring>
39 : #include <algorithm>
40 : #include <map>
41 : #include <new>
42 : #include <set>
43 : #include <string>
44 : #include <utility>
45 :
46 : #include "cpl_conv.h"
47 : #include "cpl_error.h"
48 : #include "cpl_hash_set.h"
49 : #include "cpl_multiproc.h"
50 : #include "cpl_progress.h"
51 : #include "cpl_string.h"
52 : #include "cpl_vsi.h"
53 : #include "cpl_vsi_error.h"
54 : #include "ogr_api.h"
55 : #include "ogr_attrind.h"
56 : #include "ogr_core.h"
57 : #include "ogr_feature.h"
58 : #include "ogr_featurestyle.h"
59 : #include "ogr_gensql.h"
60 : #include "ogr_geometry.h"
61 : #include "ogr_p.h"
62 : #include "ogr_spatialref.h"
63 : #include "ogr_srs_api.h"
64 : #include "ograpispy.h"
65 : #include "ogrsf_frmts.h"
66 : #include "ogrunionlayer.h"
67 : #include "ogr_swq.h"
68 :
69 : #include "../frmts/derived/derivedlist.h"
70 :
71 : #ifdef SQLITE_ENABLED
72 : #include "../sqlite/ogrsqliteexecutesql.h"
73 : #endif
74 :
75 : extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
76 :
77 : CPL_C_START
78 : GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
79 : int nYOff, int nXSize, int nYSize,
80 : void *pBuf, int nBufXSize,
81 : int nBufYSize, GDALDataType eBufType,
82 : int nBandCount, int *panBandMap,
83 : int nPixelSpace, int nLineSpace,
84 : int nBandSpace, char **papszOptions);
85 : CPL_C_END
86 :
87 : enum class GDALAllowReadWriteMutexState
88 : {
89 : RW_MUTEX_STATE_UNKNOWN,
90 : RW_MUTEX_STATE_ALLOWED,
91 : RW_MUTEX_STATE_DISABLED
92 : };
93 :
94 : const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
95 : const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
96 :
97 : class GDALDataset::Private
98 : {
99 : CPL_DISALLOW_COPY_ASSIGN(Private)
100 :
101 : public:
102 : CPLMutex *hMutex = nullptr;
103 : std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
104 : #ifdef DEBUG_EXTRA
105 : std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
106 : #endif
107 : GDALAllowReadWriteMutexState eStateReadWriteMutex =
108 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
109 : int nCurrentLayerIdx = 0;
110 : int nLayerCount = -1;
111 : GIntBig nFeatureReadInLayer = 0;
112 : GIntBig nFeatureReadInDataset = 0;
113 : GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
114 : GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
115 : OGRLayer *poCurrentLayer = nullptr;
116 :
117 : char *m_pszWKTCached = nullptr;
118 : OGRSpatialReference *m_poSRSCached = nullptr;
119 : char *m_pszWKTGCPCached = nullptr;
120 : OGRSpatialReference *m_poSRSGCPCached = nullptr;
121 :
122 : GDALDataset *poParentDataset = nullptr;
123 :
124 : bool m_bOverviewsEnabled = true;
125 :
126 115497 : Private() = default;
127 : };
128 :
129 : struct SharedDatasetCtxt
130 : {
131 : // PID of the thread that mark the dataset as shared
132 : // This may not be the actual PID, but the responsiblePID.
133 : GIntBig nPID;
134 : char *pszDescription;
135 : char *pszConcatenatedOpenOptions;
136 : int nOpenFlags;
137 :
138 : GDALDataset *poDS;
139 : };
140 :
141 : // Set of datasets opened as shared datasets (with GDALOpenShared)
142 : // The values in the set are of type SharedDatasetCtxt.
143 : static CPLHashSet *phSharedDatasetSet = nullptr;
144 :
145 : // Set of all datasets created in the constructor of GDALDataset.
146 : // In the case of a shared dataset, memorize the PID of the thread
147 : // that marked the dataset as shared, so that we can remove it from
148 : // the phSharedDatasetSet in the destructor of the dataset, even
149 : // if GDALClose is called from a different thread.
150 : static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
151 :
152 : static CPLMutex *hDLMutex = nullptr;
153 :
154 : // Static array of all datasets. Used by GDALGetOpenDatasets.
155 : // Not thread-safe. See GDALGetOpenDatasets.
156 : static GDALDataset **ppDatasets = nullptr;
157 :
158 8239 : static unsigned long GDALSharedDatasetHashFunc(const void *elt)
159 : {
160 8239 : const SharedDatasetCtxt *psStruct =
161 : static_cast<const SharedDatasetCtxt *>(elt);
162 : return static_cast<unsigned long>(
163 8239 : CPLHashSetHashStr(psStruct->pszDescription) ^
164 8239 : CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
165 8239 : psStruct->nOpenFlags ^ psStruct->nPID);
166 : }
167 :
168 6916 : static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
169 : {
170 6916 : const SharedDatasetCtxt *psStruct1 =
171 : static_cast<const SharedDatasetCtxt *>(elt1);
172 6916 : const SharedDatasetCtxt *psStruct2 =
173 : static_cast<const SharedDatasetCtxt *>(elt2);
174 13795 : return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
175 6879 : strcmp(psStruct1->pszConcatenatedOpenOptions,
176 6879 : psStruct2->pszConcatenatedOpenOptions) == 0 &&
177 20674 : psStruct1->nPID == psStruct2->nPID &&
178 13795 : psStruct1->nOpenFlags == psStruct2->nOpenFlags;
179 : }
180 :
181 383 : static void GDALSharedDatasetFreeFunc(void *elt)
182 : {
183 383 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
184 383 : CPLFree(psStruct->pszDescription);
185 383 : CPLFree(psStruct->pszConcatenatedOpenOptions);
186 383 : CPLFree(psStruct);
187 383 : }
188 :
189 : static std::string
190 6986 : GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
191 : {
192 6986 : std::string osStr;
193 6999 : for (const char *pszOption : cpl::Iterate(papszOpenOptions))
194 13 : osStr += pszOption;
195 6986 : return osStr;
196 : }
197 :
198 : /************************************************************************/
199 : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
200 : /************************************************************************/
201 :
202 : // The open-shared mutex must be used by the ProxyPool too.
203 49317 : CPLMutex **GDALGetphDLMutex()
204 : {
205 49317 : return &hDLMutex;
206 : }
207 :
208 : // The current thread will act in the behalf of the thread of PID
209 : // responsiblePID.
210 42874 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
211 : {
212 : GIntBig *pResponsiblePID =
213 42874 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
214 42874 : if (pResponsiblePID == nullptr)
215 : {
216 149 : pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
217 149 : CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
218 : }
219 42874 : *pResponsiblePID = responsiblePID;
220 42874 : }
221 :
222 : // Get the PID of the thread that the current thread will act in the behalf of
223 : // By default : the current thread acts in the behalf of itself.
224 142000 : GIntBig GDALGetResponsiblePIDForCurrentThread()
225 : {
226 : GIntBig *pResponsiblePID =
227 142000 : static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
228 141965 : if (pResponsiblePID == nullptr)
229 42813 : return CPLGetPID();
230 99152 : return *pResponsiblePID;
231 : }
232 :
233 : /************************************************************************/
234 : /* ==================================================================== */
235 : /* GDALDataset */
236 : /* ==================================================================== */
237 : /************************************************************************/
238 :
239 : /**
240 : * \class GDALDataset "gdal_priv.h"
241 : *
242 : * A dataset encapsulating one or more raster bands. Details are further
243 : * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
244 : * Raster Data Model</a>.
245 : *
246 : * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
247 : * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
248 : * dataset.
249 : */
250 :
251 : /************************************************************************/
252 : /* GDALDataset() */
253 : /************************************************************************/
254 :
255 : //! @cond Doxygen_Suppress
256 100542 : GDALDataset::GDALDataset()
257 100542 : : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
258 : {
259 100510 : }
260 :
261 115504 : GDALDataset::GDALDataset(int bForceCachedIOIn)
262 115464 : : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
263 115504 : m_poPrivate(new(std::nothrow) GDALDataset::Private)
264 : {
265 115477 : }
266 :
267 : //! @endcond
268 :
269 : /************************************************************************/
270 : /* ~GDALDataset() */
271 : /************************************************************************/
272 :
273 : /**
274 : * \brief Destroy an open GDALDataset.
275 : *
276 : * This is the accepted method of closing a GDAL dataset and deallocating
277 : * all resources associated with it.
278 : *
279 : * Equivalent of the C callable GDALClose(). Except that GDALClose() first
280 : * decrements the reference count, and then closes only if it has dropped to
281 : * zero.
282 : *
283 : * For Windows users, it is not recommended to use the delete operator on the
284 : * dataset object because of known issues when allocating and freeing memory
285 : * across module boundaries. Calling GDALClose() is then a better option.
286 : */
287 :
288 115488 : GDALDataset::~GDALDataset()
289 :
290 : {
291 : // we don't want to report destruction of datasets that
292 : // were never really open or meant as internal
293 115480 : if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
294 : {
295 54599 : if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
296 0 : CPLDebug("GDAL",
297 : "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
298 0 : GetDescription(), this, static_cast<int>(CPLGetPID()),
299 0 : static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
300 : else
301 54612 : CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
302 : }
303 :
304 115520 : if (IsMarkedSuppressOnClose())
305 : {
306 2118 : if (poDriver == nullptr ||
307 : // Someone issuing Create("foo.tif") on a
308 : // memory driver doesn't expect files with those names to be deleted
309 : // on a file system...
310 : // This is somewhat messy. Ideally there should be a way for the
311 : // driver to overload the default behavior
312 1054 : (!EQUAL(poDriver->GetDescription(), "MEM") &&
313 1030 : !EQUAL(poDriver->GetDescription(), "Memory")))
314 : {
315 1040 : VSIUnlink(GetDescription());
316 : }
317 : }
318 :
319 : /* -------------------------------------------------------------------- */
320 : /* Remove dataset from the "open" dataset list. */
321 : /* -------------------------------------------------------------------- */
322 115490 : if (!bIsInternal)
323 : {
324 110424 : CPLMutexHolderD(&hDLMutex);
325 55212 : if (poAllDatasetMap)
326 : {
327 : std::map<GDALDataset *, GIntBig>::iterator oIter =
328 55212 : poAllDatasetMap->find(this);
329 55212 : CPLAssert(oIter != poAllDatasetMap->end());
330 :
331 55212 : UnregisterFromSharedDataset();
332 :
333 55212 : poAllDatasetMap->erase(oIter);
334 :
335 55212 : if (poAllDatasetMap->empty())
336 : {
337 22497 : delete poAllDatasetMap;
338 22497 : poAllDatasetMap = nullptr;
339 22497 : if (phSharedDatasetSet)
340 : {
341 276 : CPLHashSetDestroy(phSharedDatasetSet);
342 : }
343 22497 : phSharedDatasetSet = nullptr;
344 22497 : CPLFree(ppDatasets);
345 22497 : ppDatasets = nullptr;
346 : }
347 : }
348 : }
349 :
350 : /* -------------------------------------------------------------------- */
351 : /* Destroy the raster bands if they exist. */
352 : /* -------------------------------------------------------------------- */
353 913034 : for (int i = 0; i < nBands && papoBands != nullptr; ++i)
354 : {
355 797545 : if (papoBands[i] != nullptr)
356 797545 : delete papoBands[i];
357 797544 : papoBands[i] = nullptr;
358 : }
359 :
360 115489 : CPLFree(papoBands);
361 :
362 115488 : if (m_poStyleTable)
363 : {
364 16 : delete m_poStyleTable;
365 16 : m_poStyleTable = nullptr;
366 : }
367 :
368 115488 : if (m_poPrivate != nullptr)
369 : {
370 115489 : if (m_poPrivate->hMutex != nullptr)
371 12447 : CPLDestroyMutex(m_poPrivate->hMutex);
372 :
373 115489 : CPLFree(m_poPrivate->m_pszWKTCached);
374 115490 : if (m_poPrivate->m_poSRSCached)
375 : {
376 0 : m_poPrivate->m_poSRSCached->Release();
377 : }
378 115490 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
379 115489 : if (m_poPrivate->m_poSRSGCPCached)
380 : {
381 0 : m_poPrivate->m_poSRSGCPCached->Release();
382 : }
383 : }
384 :
385 115488 : delete m_poPrivate;
386 :
387 115489 : CSLDestroy(papszOpenOptions);
388 115489 : }
389 :
390 : /************************************************************************/
391 : /* Close() */
392 : /************************************************************************/
393 :
394 : /** Do final cleanup before a dataset is destroyed.
395 : *
396 : * This method is typically called by GDALClose() or the destructor of a
397 : * GDALDataset subclass. It might also be called by C++ users before
398 : * destroying a dataset. It should not be called on a shared dataset whose
399 : * reference count is greater than one.
400 : *
401 : * It gives a last chance to the closing process to return an error code if
402 : * something goes wrong, in particular in creation / update scenarios where
403 : * file write or network communication might occur when finalizing the dataset.
404 : *
405 : * Implementations should be robust to this method to be called several times
406 : * (on subsequent calls, it should do nothing and return CE_None).
407 : * Once it has been called, no other method than Close() or the dataset
408 : * destructor should be called. RasterBand or OGRLayer owned by the dataset
409 : * should be assumed as no longer being valid.
410 : *
411 : * If a driver implements this method, it must also call it from its
412 : * dataset destructor.
413 : *
414 : * A typical implementation might look as the following
415 : * \code{.cpp}
416 : *
417 : * MyDataset::~MyDataset()
418 : * {
419 : * try
420 : * {
421 : * MyDataset::Close();
422 : * }
423 : * catch (const std::exception &exc)
424 : * {
425 : * // If Close() can throw exception
426 : * CPLError(CE_Failure, CPLE_AppDefined,
427 : * "Exception thrown in MyDataset::Close(): %s",
428 : * exc.what());
429 : * }
430 : * catch (...)
431 : * {
432 : * // If Close() can throw exception
433 : * CPLError(CE_Failure, CPLE_AppDefined,
434 : * "Exception thrown in MyDataset::Close()");
435 : * }
436 : * }
437 : *
438 : * CPLErr MyDataset::Close()
439 : * {
440 : * CPLErr eErr = CE_None;
441 : * if( nOpenFlags != OPEN_FLAGS_CLOSED )
442 : * {
443 : * if( MyDataset::FlushCache(true) != CE_None )
444 : * eErr = CE_Failure;
445 : *
446 : * // Do something driver specific
447 : * if (m_fpImage)
448 : * {
449 : * if( VSIFCloseL(m_fpImage) != 0 )
450 : * {
451 : * CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
452 : * eErr = CE_Failure;
453 : * }
454 : * }
455 : *
456 : * // Call parent Close() implementation.
457 : * if( MyParentDatasetClass::Close() != CE_None )
458 : * eErr = CE_Failure;
459 : * }
460 : * return eErr;
461 : * }
462 : * \endcode
463 : *
464 : * @since GDAL 3.7
465 : */
466 67624 : CPLErr GDALDataset::Close()
467 : {
468 : // Call UnregisterFromSharedDataset() before altering nOpenFlags
469 67624 : UnregisterFromSharedDataset();
470 :
471 67622 : nOpenFlags = OPEN_FLAGS_CLOSED;
472 67622 : return CE_None;
473 : }
474 :
475 : /************************************************************************/
476 : /* UnregisterFromSharedDataset() */
477 : /************************************************************************/
478 :
479 122836 : void GDALDataset::UnregisterFromSharedDataset()
480 : {
481 122836 : if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
482 122453 : return;
483 :
484 766 : CPLMutexHolderD(&hDLMutex);
485 :
486 : std::map<GDALDataset *, GIntBig>::iterator oIter =
487 383 : poAllDatasetMap->find(this);
488 383 : CPLAssert(oIter != poAllDatasetMap->end());
489 383 : const GIntBig nPIDCreatorForShared = oIter->second;
490 383 : bShared = false;
491 : SharedDatasetCtxt sStruct;
492 383 : sStruct.nPID = nPIDCreatorForShared;
493 383 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
494 383 : sStruct.pszDescription = const_cast<char *>(GetDescription());
495 : std::string osConcatenatedOpenOptions =
496 766 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
497 383 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
498 383 : sStruct.poDS = nullptr;
499 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
500 383 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
501 383 : if (psStruct && psStruct->poDS == this)
502 : {
503 382 : CPLHashSetRemove(phSharedDatasetSet, psStruct);
504 : }
505 : else
506 : {
507 1 : CPLDebug("GDAL",
508 : "Should not happen. Cannot find %s, "
509 : "this=%p in phSharedDatasetSet",
510 1 : GetDescription(), this);
511 : }
512 : }
513 :
514 : /************************************************************************/
515 : /* AddToDatasetOpenList() */
516 : /************************************************************************/
517 :
518 56597 : void GDALDataset::AddToDatasetOpenList()
519 : {
520 : /* -------------------------------------------------------------------- */
521 : /* Add this dataset to the open dataset list. */
522 : /* -------------------------------------------------------------------- */
523 56597 : bIsInternal = false;
524 :
525 56597 : CPLMutexHolderD(&hDLMutex);
526 :
527 56597 : if (poAllDatasetMap == nullptr)
528 22506 : poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
529 56597 : (*poAllDatasetMap)[this] = -1;
530 56597 : }
531 :
532 : /************************************************************************/
533 : /* FlushCache() */
534 : /************************************************************************/
535 :
536 : /**
537 : * \brief Flush all write cached data to disk.
538 : *
539 : * Any raster (or other GDAL) data written via GDAL calls, but buffered
540 : * internally will be written to disk.
541 : *
542 : * The default implementation of this method just calls the FlushCache() method
543 : * on each of the raster bands and the SyncToDisk() method
544 : * on each of the layers. Conceptionally, calling FlushCache() on a dataset
545 : * should include any work that might be accomplished by calling SyncToDisk()
546 : * on layers in that dataset.
547 : *
548 : * Using this method does not prevent use from calling GDALClose()
549 : * to properly close a dataset and ensure that important data not addressed
550 : * by FlushCache() is written in the file.
551 : *
552 : * This method is the same as the C function GDALFlushCache().
553 : *
554 : * @param bAtClosing Whether this is called from a GDALDataset destructor
555 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
556 : */
557 :
558 85196 : CPLErr GDALDataset::FlushCache(bool bAtClosing)
559 :
560 : {
561 85196 : CPLErr eErr = CE_None;
562 : // This sometimes happens if a dataset is destroyed before completely
563 : // built.
564 :
565 85196 : if (papoBands)
566 : {
567 1237130 : for (int i = 0; i < nBands; ++i)
568 : {
569 1159080 : if (papoBands[i])
570 : {
571 1159080 : if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
572 8 : eErr = CE_Failure;
573 : }
574 : }
575 : }
576 :
577 85196 : const int nLayers = GetLayerCount();
578 : // cppcheck-suppress knownConditionTrueFalse
579 85198 : if (nLayers > 0)
580 : {
581 6394 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
582 11303 : for (int i = 0; i < nLayers; ++i)
583 : {
584 8106 : OGRLayer *poLayer = GetLayer(i);
585 :
586 8106 : if (poLayer)
587 : {
588 8106 : if (poLayer->SyncToDisk() != OGRERR_NONE)
589 0 : eErr = CE_Failure;
590 : }
591 : }
592 : }
593 :
594 85198 : return eErr;
595 : }
596 :
597 : /************************************************************************/
598 : /* GDALFlushCache() */
599 : /************************************************************************/
600 :
601 : /**
602 : * \brief Flush all write cached data to disk.
603 : *
604 : * @see GDALDataset::FlushCache().
605 : * @return CE_None in case of success (note: return value added in GDAL 3.7)
606 : */
607 :
608 3315 : CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
609 :
610 : {
611 3315 : VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
612 :
613 3315 : return GDALDataset::FromHandle(hDS)->FlushCache(false);
614 : }
615 :
616 : /************************************************************************/
617 : /* DropCache() */
618 : /************************************************************************/
619 :
620 : /**
621 : * \brief Drop all write cached data
622 : *
623 : * This method is the same as the C function GDALDropCache().
624 : *
625 : * @return CE_None in case of success
626 : * @since 3.9
627 : */
628 :
629 1 : CPLErr GDALDataset::DropCache()
630 :
631 : {
632 1 : CPLErr eErr = CE_None;
633 :
634 1 : if (papoBands)
635 : {
636 2 : for (int i = 0; i < nBands; ++i)
637 : {
638 1 : if (papoBands[i])
639 : {
640 1 : if (papoBands[i]->DropCache() != CE_None)
641 0 : eErr = CE_Failure;
642 : }
643 : }
644 : }
645 :
646 1 : return eErr;
647 : }
648 :
649 : /************************************************************************/
650 : /* GDALDropCache() */
651 : /************************************************************************/
652 :
653 : /**
654 : * \brief Drop all write cached data
655 : *
656 : * @see GDALDataset::DropCache().
657 : * @return CE_None in case of success
658 : * @since 3.9
659 : */
660 :
661 0 : CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
662 :
663 : {
664 0 : VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
665 :
666 0 : return GDALDataset::FromHandle(hDS)->DropCache();
667 : }
668 :
669 : /************************************************************************/
670 : /* GetEstimatedRAMUsage() */
671 : /************************************************************************/
672 :
673 : /**
674 : * \brief Return the intrinsic RAM usage of this dataset.
675 : *
676 : * The returned value should take into account caches in the underlying driver
677 : * and decoding library, but not the usage related to the GDAL block cache.
678 : *
679 : * At time of writing, this method is only implemented in the JP2OpenJPEG
680 : * driver. For single-tiled JPEG2000 images, the decoding of the image,
681 : * even partially, involves allocating at least
682 : * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
683 : * library.
684 : *
685 : * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
686 : * driver, to determine how long a dataset in the pool must be kept open, given
687 : * the RAM usage of the dataset with respect to the usable total RAM.
688 : *
689 : * @since GDAL 3.7
690 : * @return RAM usage in bytes, or -1 if unknown (the default implementation
691 : * returns -1)
692 : */
693 :
694 668 : GIntBig GDALDataset::GetEstimatedRAMUsage()
695 : {
696 668 : return -1;
697 : }
698 :
699 : /************************************************************************/
700 : /* BlockBasedFlushCache() */
701 : /* */
702 : /* This helper method can be called by the */
703 : /* GDALDataset::FlushCache() for particular drivers to ensure */
704 : /* that buffers will be flushed in a manner suitable for pixel */
705 : /* interleaved (by block) IO. That is, if all the bands have */
706 : /* the same size blocks then a given block will be flushed for */
707 : /* all bands before proceeding to the next block. */
708 : /************************************************************************/
709 :
710 : //! @cond Doxygen_Suppress
711 231 : CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
712 :
713 : {
714 231 : GDALRasterBand *poBand1 = GetRasterBand(1);
715 231 : if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
716 : {
717 16 : return GDALDataset::FlushCache(bAtClosing);
718 : }
719 :
720 215 : int nBlockXSize = 0;
721 215 : int nBlockYSize = 0;
722 215 : poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
723 :
724 : /* -------------------------------------------------------------------- */
725 : /* Verify that all bands match. */
726 : /* -------------------------------------------------------------------- */
727 899 : for (int iBand = 1; iBand < nBands; ++iBand)
728 : {
729 684 : GDALRasterBand *poBand = GetRasterBand(iBand + 1);
730 :
731 : int nThisBlockXSize, nThisBlockYSize;
732 684 : poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
733 684 : if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
734 : {
735 0 : return GDALDataset::FlushCache(bAtClosing);
736 : }
737 : }
738 :
739 : /* -------------------------------------------------------------------- */
740 : /* Now flush writable data. */
741 : /* -------------------------------------------------------------------- */
742 662 : for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
743 : {
744 984 : for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
745 : {
746 1677 : for (int iBand = 0; iBand < nBands; ++iBand)
747 : {
748 1141 : GDALRasterBand *poBand = GetRasterBand(iBand + 1);
749 :
750 1141 : const CPLErr eErr = poBand->FlushBlock(iX, iY);
751 :
752 1141 : if (eErr != CE_None)
753 1 : return CE_Failure;
754 : }
755 : }
756 : }
757 214 : return CE_None;
758 : }
759 :
760 : /************************************************************************/
761 : /* RasterInitialize() */
762 : /* */
763 : /* Initialize raster size */
764 : /************************************************************************/
765 :
766 0 : void GDALDataset::RasterInitialize(int nXSize, int nYSize)
767 :
768 : {
769 0 : CPLAssert(nXSize > 0 && nYSize > 0);
770 :
771 0 : nRasterXSize = nXSize;
772 0 : nRasterYSize = nYSize;
773 0 : }
774 :
775 : //! @endcond
776 :
777 : /************************************************************************/
778 : /* AddBand() */
779 : /************************************************************************/
780 :
781 : /**
782 : * \fn GDALDataset::AddBand(GDALDataType, char**)
783 : * \brief Add a band to a dataset.
784 : *
785 : * This method will add a new band to the dataset if the underlying format
786 : * supports this action. Most formats do not.
787 : *
788 : * Note that the new GDALRasterBand is not returned. It may be fetched
789 : * after successful completion of the method by calling
790 : * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
791 : * band will always be the last band.
792 : *
793 : * @param eType the data type of the pixels in the new band.
794 : *
795 : * @param papszOptions a list of NAME=VALUE option strings. The supported
796 : * options are format specific. NULL may be passed by default.
797 : *
798 : * @return CE_None on success or CE_Failure on failure.
799 : */
800 :
801 0 : CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
802 : CPL_UNUSED char **papszOptions)
803 :
804 : {
805 0 : ReportError(CE_Failure, CPLE_NotSupported,
806 : "Dataset does not support the AddBand() method.");
807 :
808 0 : return CE_Failure;
809 : }
810 :
811 : /************************************************************************/
812 : /* GDALAddBand() */
813 : /************************************************************************/
814 :
815 : /**
816 : * \brief Add a band to a dataset.
817 : *
818 : * @see GDALDataset::AddBand().
819 : */
820 :
821 58 : CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
822 : CSLConstList papszOptions)
823 :
824 : {
825 58 : VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
826 :
827 116 : return GDALDataset::FromHandle(hDataset)->AddBand(
828 58 : eType, const_cast<char **>(papszOptions));
829 : }
830 :
831 : /************************************************************************/
832 : /* SetBand() */
833 : /************************************************************************/
834 :
835 : //! @cond Doxygen_Suppress
836 : /** Set a band in the band array, updating the band count, and array size
837 : * appropriately.
838 : *
839 : * @param nNewBand new band number (indexing starts at 1)
840 : * @param poBand band object.
841 : */
842 :
843 1012360 : void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
844 :
845 : {
846 : /* -------------------------------------------------------------------- */
847 : /* Do we need to grow the bands list? */
848 : /* -------------------------------------------------------------------- */
849 1012360 : if (nBands < nNewBand || papoBands == nullptr)
850 : {
851 516802 : GDALRasterBand **papoNewBands = nullptr;
852 :
853 516802 : if (papoBands == nullptr)
854 69560 : papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
855 69539 : sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
856 : else
857 : papoNewBands = static_cast<GDALRasterBand **>(
858 447248 : VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
859 447263 : std::max(nNewBand, nBands)));
860 516808 : if (papoNewBands == nullptr)
861 : {
862 0 : ReportError(CE_Failure, CPLE_OutOfMemory,
863 : "Cannot allocate band array");
864 0 : return;
865 : }
866 :
867 516808 : papoBands = papoNewBands;
868 :
869 994134 : for (int i = nBands; i < nNewBand; ++i)
870 477326 : papoBands[i] = nullptr;
871 :
872 516808 : nBands = std::max(nBands, nNewBand);
873 : }
874 :
875 : /* -------------------------------------------------------------------- */
876 : /* Set the band. Resetting the band is currently not permitted. */
877 : /* -------------------------------------------------------------------- */
878 1012380 : if (papoBands[nNewBand - 1] != nullptr)
879 : {
880 0 : ReportError(CE_Failure, CPLE_NotSupported,
881 : "Cannot set band %d as it is already set", nNewBand);
882 0 : return;
883 : }
884 :
885 1012380 : papoBands[nNewBand - 1] = poBand;
886 :
887 : /* -------------------------------------------------------------------- */
888 : /* Set back reference information on the raster band. Note */
889 : /* that the GDALDataset is a friend of the GDALRasterBand */
890 : /* specifically to allow this. */
891 : /* -------------------------------------------------------------------- */
892 1012380 : poBand->nBand = nNewBand;
893 1012380 : poBand->poDS = this;
894 1012380 : poBand->nRasterXSize = nRasterXSize;
895 1012380 : poBand->nRasterYSize = nRasterYSize;
896 1012380 : poBand->eAccess = eAccess; // Default access to be same as dataset.
897 : }
898 :
899 : //! @endcond
900 :
901 : /************************************************************************/
902 : /* SetBand() */
903 : /************************************************************************/
904 :
905 : //! @cond Doxygen_Suppress
906 : /** Set a band in the band array, updating the band count, and array size
907 : * appropriately.
908 : *
909 : * @param nNewBand new band number (indexing starts at 1)
910 : * @param poBand band object.
911 : */
912 :
913 4295 : void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
914 : {
915 4295 : SetBand(nNewBand, poBand.release());
916 4295 : }
917 :
918 : //! @endcond
919 :
920 : /************************************************************************/
921 : /* GetRasterXSize() */
922 : /************************************************************************/
923 :
924 : /**
925 :
926 : \brief Fetch raster width in pixels.
927 :
928 : Equivalent of the C function GDALGetRasterXSize().
929 :
930 : @return the width in pixels of raster bands in this GDALDataset.
931 :
932 : */
933 :
934 1007470 : int GDALDataset::GetRasterXSize() const
935 : {
936 1007470 : return nRasterXSize;
937 : }
938 :
939 : /************************************************************************/
940 : /* GDALGetRasterXSize() */
941 : /************************************************************************/
942 :
943 : /**
944 : * \brief Fetch raster width in pixels.
945 : *
946 : * @see GDALDataset::GetRasterXSize().
947 : */
948 :
949 30590 : int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
950 :
951 : {
952 30590 : VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
953 :
954 30590 : return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
955 : }
956 :
957 : /************************************************************************/
958 : /* GetRasterYSize() */
959 : /************************************************************************/
960 :
961 : /**
962 :
963 : \brief Fetch raster height in pixels.
964 :
965 : Equivalent of the C function GDALGetRasterYSize().
966 :
967 : @return the height in pixels of raster bands in this GDALDataset.
968 :
969 : */
970 :
971 934486 : int GDALDataset::GetRasterYSize() const
972 : {
973 934486 : return nRasterYSize;
974 : }
975 :
976 : /************************************************************************/
977 : /* GDALGetRasterYSize() */
978 : /************************************************************************/
979 :
980 : /**
981 : * \brief Fetch raster height in pixels.
982 : *
983 : * @see GDALDataset::GetRasterYSize().
984 : */
985 :
986 30429 : int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
987 :
988 : {
989 30429 : VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
990 :
991 30429 : return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
992 : }
993 :
994 : /************************************************************************/
995 : /* GetRasterBand() */
996 : /************************************************************************/
997 :
998 : /**
999 :
1000 : \brief Fetch a band object for a dataset.
1001 :
1002 : See GetBands() for a C++ iterator version of this method.
1003 :
1004 : Equivalent of the C function GDALGetRasterBand().
1005 :
1006 : @param nBandId the index number of the band to fetch, from 1 to
1007 : GetRasterCount().
1008 :
1009 : @return the nBandId th band object
1010 :
1011 : */
1012 :
1013 8007900 : GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1014 :
1015 : {
1016 8007900 : if (papoBands)
1017 : {
1018 8007810 : if (nBandId < 1 || nBandId > nBands)
1019 : {
1020 244 : ReportError(CE_Failure, CPLE_IllegalArg,
1021 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1022 : nBandId);
1023 13 : return nullptr;
1024 : }
1025 :
1026 8007560 : return papoBands[nBandId - 1];
1027 : }
1028 89 : return nullptr;
1029 : }
1030 :
1031 : /************************************************************************/
1032 : /* GetRasterBand() */
1033 : /************************************************************************/
1034 :
1035 : /**
1036 :
1037 : \brief Fetch a band object for a dataset.
1038 :
1039 : See GetBands() for a C++ iterator version of this method.
1040 :
1041 : Equivalent of the C function GDALGetRasterBand().
1042 :
1043 : @param nBandId the index number of the band to fetch, from 1 to
1044 : GetRasterCount().
1045 :
1046 : @return the nBandId th band object
1047 :
1048 : */
1049 :
1050 0 : const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1051 :
1052 : {
1053 0 : if (papoBands)
1054 : {
1055 0 : if (nBandId < 1 || nBandId > nBands)
1056 : {
1057 0 : ReportError(CE_Failure, CPLE_IllegalArg,
1058 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1059 : nBandId);
1060 0 : return nullptr;
1061 : }
1062 :
1063 0 : return papoBands[nBandId - 1];
1064 : }
1065 0 : return nullptr;
1066 : }
1067 :
1068 : /************************************************************************/
1069 : /* GDALGetRasterBand() */
1070 : /************************************************************************/
1071 :
1072 : /**
1073 : * \brief Fetch a band object for a dataset.
1074 : * @see GDALDataset::GetRasterBand().
1075 : */
1076 :
1077 256511 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1078 :
1079 : {
1080 256511 : VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1081 :
1082 256511 : return GDALRasterBand::ToHandle(
1083 256511 : GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
1084 : }
1085 :
1086 : /************************************************************************/
1087 : /* GetRasterCount() */
1088 : /************************************************************************/
1089 :
1090 : /**
1091 : * \brief Fetch the number of raster bands on this dataset.
1092 : *
1093 : * Same as the C function GDALGetRasterCount().
1094 : *
1095 : * @return the number of raster bands.
1096 : */
1097 :
1098 3764000 : int GDALDataset::GetRasterCount() const
1099 : {
1100 3764000 : return papoBands ? nBands : 0;
1101 : }
1102 :
1103 : /************************************************************************/
1104 : /* GDALGetRasterCount() */
1105 : /************************************************************************/
1106 :
1107 : /**
1108 : * \brief Fetch the number of raster bands on this dataset.
1109 : *
1110 : * @see GDALDataset::GetRasterCount().
1111 : */
1112 :
1113 370085 : int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1114 :
1115 : {
1116 370085 : VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1117 :
1118 370085 : return GDALDataset::FromHandle(hDS)->GetRasterCount();
1119 : }
1120 :
1121 : /************************************************************************/
1122 : /* GetProjectionRef() */
1123 : /************************************************************************/
1124 :
1125 : /**
1126 : * \brief Fetch the projection definition string for this dataset.
1127 : *
1128 : * Same as the C function GDALGetProjectionRef().
1129 : *
1130 : * The returned string defines the projection coordinate system of the
1131 : * image in OpenGIS WKT format. It should be suitable for use with the
1132 : * OGRSpatialReference class.
1133 : *
1134 : * When a projection definition is not available an empty (but not NULL)
1135 : * string is returned.
1136 : *
1137 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1138 : * GetSpatialRef()
1139 : *
1140 : * @return a pointer to an internal projection reference string. It should
1141 : * not be altered, freed or expected to last for long.
1142 : *
1143 : * @see https://gdal.org/tutorials/osr_api_tut.html
1144 : */
1145 :
1146 5061 : const char *GDALDataset::GetProjectionRef() const
1147 : {
1148 5061 : const auto poSRS = GetSpatialRef();
1149 5061 : if (!poSRS || !m_poPrivate)
1150 : {
1151 2325 : return "";
1152 : }
1153 2736 : char *pszWKT = nullptr;
1154 2736 : poSRS->exportToWkt(&pszWKT);
1155 2736 : if (!pszWKT)
1156 : {
1157 0 : return "";
1158 : }
1159 2736 : if (m_poPrivate->m_pszWKTCached &&
1160 1097 : strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1161 : {
1162 1096 : CPLFree(pszWKT);
1163 1096 : return m_poPrivate->m_pszWKTCached;
1164 : }
1165 1640 : CPLFree(m_poPrivate->m_pszWKTCached);
1166 1640 : m_poPrivate->m_pszWKTCached = pszWKT;
1167 1640 : return m_poPrivate->m_pszWKTCached;
1168 : }
1169 :
1170 : /************************************************************************/
1171 : /* GetSpatialRef() */
1172 : /************************************************************************/
1173 :
1174 : /**
1175 : * \brief Fetch the spatial reference for this dataset.
1176 : *
1177 : * Same as the C function GDALGetSpatialRef().
1178 : *
1179 : * When a projection definition is not available, null is returned. If used on
1180 : * a dataset where there are GCPs and not a geotransform, this method returns
1181 : * null. Use GetGCPSpatialRef() instead.
1182 : *
1183 : * @since GDAL 3.0
1184 : *
1185 : * @return a pointer to an internal object. It should not be altered or freed.
1186 : * Its lifetime will be the one of the dataset object, or until the next
1187 : * call to this method.
1188 : *
1189 : * @see https://gdal.org/tutorials/osr_api_tut.html
1190 : */
1191 :
1192 11674 : const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1193 : {
1194 11674 : return nullptr;
1195 : }
1196 :
1197 : /************************************************************************/
1198 : /* GDALGetSpatialRef() */
1199 : /************************************************************************/
1200 :
1201 : /**
1202 : * \brief Fetch the spatial reference for this dataset.
1203 : *
1204 : * @since GDAL 3.0
1205 : *
1206 : * @see GDALDataset::GetSpatialRef()
1207 : */
1208 :
1209 5070 : OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1210 :
1211 : {
1212 5070 : VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1213 :
1214 5070 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1215 5070 : GDALDataset::FromHandle(hDS)->GetSpatialRef()));
1216 : }
1217 :
1218 : /************************************************************************/
1219 : /* GDALGetProjectionRef() */
1220 : /************************************************************************/
1221 :
1222 : /**
1223 : * \brief Fetch the projection definition string for this dataset.
1224 : *
1225 : * @see GDALDataset::GetProjectionRef()
1226 : */
1227 :
1228 959 : const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1229 :
1230 : {
1231 959 : VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1232 :
1233 959 : return GDALDataset::FromHandle(hDS)->GetProjectionRef();
1234 : }
1235 :
1236 : /************************************************************************/
1237 : /* SetProjection() */
1238 : /************************************************************************/
1239 :
1240 : /**
1241 : * \brief Set the projection reference string for this dataset.
1242 : *
1243 : * The string should be in OGC WKT or PROJ.4 format. An error may occur
1244 : * because of incorrectly specified projection strings, because the dataset
1245 : * is not writable, or because the dataset does not support the indicated
1246 : * projection. Many formats do not support writing projections.
1247 : *
1248 : * This method is the same as the C GDALSetProjection() function.
1249 : *
1250 : * \note Startig with GDAL 3.0, this is a compatibility layer around
1251 : * SetSpatialRef()
1252 :
1253 : * @param pszProjection projection reference string.
1254 : *
1255 : * @return CE_Failure if an error occurs, otherwise CE_None.
1256 : */
1257 :
1258 2391 : CPLErr GDALDataset::SetProjection(const char *pszProjection)
1259 : {
1260 2391 : if (pszProjection && pszProjection[0] != '\0')
1261 : {
1262 4510 : OGRSpatialReference oSRS;
1263 2255 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1264 2255 : if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1265 : {
1266 2 : return CE_Failure;
1267 : }
1268 2253 : return SetSpatialRef(&oSRS);
1269 : }
1270 : else
1271 : {
1272 136 : return SetSpatialRef(nullptr);
1273 : }
1274 : }
1275 :
1276 : /************************************************************************/
1277 : /* SetSpatialRef() */
1278 : /************************************************************************/
1279 :
1280 : /**
1281 : * \brief Set the spatial reference system for this dataset.
1282 : *
1283 : * An error may occur because the dataset
1284 : * is not writable, or because the dataset does not support the indicated
1285 : * projection. Many formats do not support writing projections.
1286 : *
1287 : * This method is the same as the C GDALSetSpatialRef() function.
1288 : *
1289 : * @since GDAL 3.0
1290 :
1291 : * @param poSRS spatial reference system object. nullptr can potentially be
1292 : * passed for drivers that support unsetting the SRS.
1293 : *
1294 : * @return CE_Failure if an error occurs, otherwise CE_None.
1295 : */
1296 :
1297 0 : CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
1298 : {
1299 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1300 0 : ReportError(CE_Failure, CPLE_NotSupported,
1301 : "Dataset does not support the SetSpatialRef() method.");
1302 0 : return CE_Failure;
1303 : }
1304 :
1305 : /************************************************************************/
1306 : /* GDALSetSpatialRef() */
1307 : /************************************************************************/
1308 :
1309 : /**
1310 : * \brief Set the spatial reference system for this dataset.
1311 : *
1312 : * @since GDAL 3.0
1313 : *
1314 : * @see GDALDataset::SetSpatialRef()
1315 : */
1316 :
1317 924 : CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1318 :
1319 : {
1320 924 : VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1321 :
1322 1848 : return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1323 924 : OGRSpatialReference::FromHandle(hSRS));
1324 : }
1325 :
1326 : /************************************************************************/
1327 : /* GDALSetProjection() */
1328 : /************************************************************************/
1329 :
1330 : /**
1331 : * \brief Set the projection reference string for this dataset.
1332 : *
1333 : * @see GDALDataset::SetProjection()
1334 : */
1335 :
1336 1908 : CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1337 : const char *pszProjection)
1338 :
1339 : {
1340 1908 : VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1341 :
1342 1908 : return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1343 : }
1344 :
1345 : /************************************************************************/
1346 : /* GetGeoTransform() */
1347 : /************************************************************************/
1348 :
1349 : /**
1350 : * \brief Fetch the affine transformation coefficients.
1351 : *
1352 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
1353 : * space, and projection coordinates (Xp,Yp) space.
1354 : *
1355 : * \code
1356 : * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1357 : * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1358 : * \endcode
1359 : *
1360 : * In a north up image, padfTransform[1] is the pixel width, and
1361 : * padfTransform[5] is the pixel height. The upper left corner of the
1362 : * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1363 : *
1364 : * The default transform is (0,1,0,0,0,1) and should be returned even when
1365 : * a CE_Failure error is returned, such as for formats that don't support
1366 : * transformation to projection coordinates.
1367 : *
1368 : * This method does the same thing as the C GDALGetGeoTransform() function.
1369 : *
1370 : * @param padfTransform an existing six double buffer into which the
1371 : * transformation will be placed.
1372 : *
1373 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
1374 : */
1375 :
1376 10438 : CPLErr GDALDataset::GetGeoTransform(double *padfTransform)
1377 :
1378 : {
1379 10438 : CPLAssert(padfTransform != nullptr);
1380 :
1381 10438 : padfTransform[0] = 0.0; // X Origin (top left corner)
1382 10438 : padfTransform[1] = 1.0; // X Pixel size */
1383 10438 : padfTransform[2] = 0.0;
1384 :
1385 10438 : padfTransform[3] = 0.0; // Y Origin (top left corner)
1386 10438 : padfTransform[4] = 0.0;
1387 10438 : padfTransform[5] = 1.0; // Y Pixel Size
1388 :
1389 10438 : return CE_Failure;
1390 : }
1391 :
1392 : /************************************************************************/
1393 : /* GDALGetGeoTransform() */
1394 : /************************************************************************/
1395 :
1396 : /**
1397 : * \brief Fetch the affine transformation coefficients.
1398 : *
1399 : * @see GDALDataset::GetGeoTransform()
1400 : */
1401 :
1402 7161 : CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1403 :
1404 : {
1405 7161 : VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1406 :
1407 7161 : return GDALDataset::FromHandle(hDS)->GetGeoTransform(padfTransform);
1408 : }
1409 :
1410 : /************************************************************************/
1411 : /* SetGeoTransform() */
1412 : /************************************************************************/
1413 :
1414 : /**
1415 : * \fn GDALDataset::SetGeoTransform(double*)
1416 : * \brief Set the affine transformation coefficients.
1417 : *
1418 : * See GetGeoTransform() for details on the meaning of the padfTransform
1419 : * coefficients.
1420 : *
1421 : * This method does the same thing as the C GDALSetGeoTransform() function.
1422 : *
1423 : * @param padfTransform a six double buffer containing the transformation
1424 : * coefficients to be written with the dataset.
1425 : *
1426 : * @return CE_None on success, or CE_Failure if this transform cannot be
1427 : * written.
1428 : */
1429 :
1430 0 : CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED double *padfTransform)
1431 :
1432 : {
1433 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1434 0 : ReportError(CE_Failure, CPLE_NotSupported,
1435 : "SetGeoTransform() not supported for this dataset.");
1436 :
1437 0 : return CE_Failure;
1438 : }
1439 :
1440 : /************************************************************************/
1441 : /* GDALSetGeoTransform() */
1442 : /************************************************************************/
1443 :
1444 : /**
1445 : * \brief Set the affine transformation coefficients.
1446 : *
1447 : * @see GDALDataset::SetGeoTransform()
1448 : */
1449 :
1450 3572 : CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1451 :
1452 : {
1453 3572 : VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1454 :
1455 3572 : return GDALDataset::FromHandle(hDS)->SetGeoTransform(padfTransform);
1456 : }
1457 :
1458 : /************************************************************************/
1459 : /* GetInternalHandle() */
1460 : /************************************************************************/
1461 :
1462 : /**
1463 : * \fn GDALDataset::GetInternalHandle(const char*)
1464 : * \brief Fetch a format specific internally meaningful handle.
1465 : *
1466 : * This method is the same as the C GDALGetInternalHandle() method.
1467 : *
1468 : * @param pszHandleName the handle name desired. The meaningful names
1469 : * will be specific to the file format.
1470 : *
1471 : * @return the desired handle value, or NULL if not recognized/supported.
1472 : */
1473 :
1474 0 : void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
1475 :
1476 : {
1477 0 : return nullptr;
1478 : }
1479 :
1480 : /************************************************************************/
1481 : /* GDALGetInternalHandle() */
1482 : /************************************************************************/
1483 :
1484 : /**
1485 : * \brief Fetch a format specific internally meaningful handle.
1486 : *
1487 : * @see GDALDataset::GetInternalHandle()
1488 : */
1489 :
1490 58 : void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
1491 : const char *pszRequest)
1492 :
1493 : {
1494 58 : VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1495 :
1496 58 : return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1497 : }
1498 :
1499 : /************************************************************************/
1500 : /* GetDriver() */
1501 : /************************************************************************/
1502 :
1503 : /**
1504 : * \brief Fetch the driver to which this dataset relates.
1505 : *
1506 : * This method is the same as the C GDALGetDatasetDriver() function.
1507 : *
1508 : * @return the driver on which the dataset was created with GDALOpen() or
1509 : * GDALCreate().
1510 : */
1511 :
1512 26807 : GDALDriver *GDALDataset::GetDriver()
1513 : {
1514 26807 : return poDriver;
1515 : }
1516 :
1517 : /************************************************************************/
1518 : /* GDALGetDatasetDriver() */
1519 : /************************************************************************/
1520 :
1521 : /**
1522 : * \brief Fetch the driver to which this dataset relates.
1523 : *
1524 : * @see GDALDataset::GetDriver()
1525 : */
1526 :
1527 2605 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1528 :
1529 : {
1530 2605 : VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1531 :
1532 : return static_cast<GDALDriverH>(
1533 2605 : GDALDataset::FromHandle(hDataset)->GetDriver());
1534 : }
1535 :
1536 : /************************************************************************/
1537 : /* Reference() */
1538 : /************************************************************************/
1539 :
1540 : /**
1541 : * \brief Add one to dataset reference count.
1542 : *
1543 : * The reference is one after instantiation.
1544 : *
1545 : * This method is the same as the C GDALReferenceDataset() function.
1546 : *
1547 : * @return the post-increment reference count.
1548 : */
1549 :
1550 13381 : int GDALDataset::Reference()
1551 : {
1552 13381 : return ++nRefCount;
1553 : }
1554 :
1555 : /************************************************************************/
1556 : /* GDALReferenceDataset() */
1557 : /************************************************************************/
1558 :
1559 : /**
1560 : * \brief Add one to dataset reference count.
1561 : *
1562 : * @see GDALDataset::Reference()
1563 : */
1564 :
1565 1025 : int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1566 :
1567 : {
1568 1025 : VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1569 :
1570 1025 : return GDALDataset::FromHandle(hDataset)->Reference();
1571 : }
1572 :
1573 : /************************************************************************/
1574 : /* Dereference() */
1575 : /************************************************************************/
1576 :
1577 : /**
1578 : * \brief Subtract one from dataset reference count.
1579 : *
1580 : * The reference is one after instantiation. Generally when the reference
1581 : * count has dropped to zero the dataset may be safely deleted (closed).
1582 : *
1583 : * This method is the same as the C GDALDereferenceDataset() function.
1584 : *
1585 : * @return the post-decrement reference count.
1586 : */
1587 :
1588 58266 : int GDALDataset::Dereference()
1589 : {
1590 58266 : return --nRefCount;
1591 : }
1592 :
1593 : /************************************************************************/
1594 : /* GDALDereferenceDataset() */
1595 : /************************************************************************/
1596 :
1597 : /**
1598 : * \brief Subtract one from dataset reference count.
1599 : *
1600 : * @see GDALDataset::Dereference()
1601 : */
1602 :
1603 49274 : int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1604 :
1605 : {
1606 49274 : VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1607 :
1608 49274 : return GDALDataset::FromHandle(hDataset)->Dereference();
1609 : }
1610 :
1611 : /************************************************************************/
1612 : /* ReleaseRef() */
1613 : /************************************************************************/
1614 :
1615 : /**
1616 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1617 : * @return TRUE if the object has been destroyed.
1618 : * @since GDAL 2.2
1619 : */
1620 :
1621 8406 : int GDALDataset::ReleaseRef()
1622 :
1623 : {
1624 8406 : if (Dereference() <= 0)
1625 : {
1626 2231 : nRefCount = 1;
1627 2231 : delete this;
1628 2231 : return TRUE;
1629 : }
1630 6175 : return FALSE;
1631 : }
1632 :
1633 : /************************************************************************/
1634 : /* GDALReleaseDataset() */
1635 : /************************************************************************/
1636 :
1637 : /**
1638 : * \brief Drop a reference to this object, and destroy if no longer referenced.
1639 : *
1640 : * @see GDALDataset::ReleaseRef()
1641 : * @since GDAL 2.2
1642 : */
1643 :
1644 1267 : int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1645 :
1646 : {
1647 1267 : VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1648 :
1649 1267 : return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1650 : }
1651 :
1652 : /************************************************************************/
1653 : /* GetShared() */
1654 : /************************************************************************/
1655 :
1656 : /**
1657 : * \brief Returns shared flag.
1658 : *
1659 : * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1660 : */
1661 :
1662 81320 : int GDALDataset::GetShared() const
1663 : {
1664 81320 : return bShared;
1665 : }
1666 :
1667 : /************************************************************************/
1668 : /* MarkAsShared() */
1669 : /************************************************************************/
1670 :
1671 : /**
1672 : * \brief Mark this dataset as available for sharing.
1673 : */
1674 :
1675 396 : void GDALDataset::MarkAsShared()
1676 :
1677 : {
1678 396 : CPLAssert(!bShared);
1679 :
1680 396 : bShared = true;
1681 396 : if (bIsInternal)
1682 13 : return;
1683 :
1684 383 : GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1685 :
1686 : // Insert the dataset in the set of shared opened datasets.
1687 766 : CPLMutexHolderD(&hDLMutex);
1688 383 : if (phSharedDatasetSet == nullptr)
1689 276 : phSharedDatasetSet =
1690 276 : CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1691 : GDALSharedDatasetFreeFunc);
1692 :
1693 : SharedDatasetCtxt *psStruct =
1694 383 : static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1695 383 : psStruct->poDS = this;
1696 383 : psStruct->nPID = nPID;
1697 383 : psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1698 383 : psStruct->pszDescription = CPLStrdup(GetDescription());
1699 : std::string osConcatenatedOpenOptions =
1700 766 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1701 383 : psStruct->pszConcatenatedOpenOptions =
1702 383 : CPLStrdup(osConcatenatedOpenOptions.c_str());
1703 383 : if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1704 : {
1705 1 : GDALSharedDatasetFreeFunc(psStruct);
1706 1 : ReportError(CE_Failure, CPLE_AppDefined,
1707 : "An existing shared dataset already has this description. "
1708 : "This should not happen.");
1709 : }
1710 : else
1711 : {
1712 382 : CPLHashSetInsert(phSharedDatasetSet, psStruct);
1713 :
1714 382 : (*poAllDatasetMap)[this] = nPID;
1715 : }
1716 : }
1717 :
1718 : /************************************************************************/
1719 : /* MarkSuppressOnClose() */
1720 : /************************************************************************/
1721 :
1722 : /** Set that the dataset must be deleted on close. */
1723 1065 : void GDALDataset::MarkSuppressOnClose()
1724 : {
1725 1065 : bSuppressOnClose = true;
1726 1065 : }
1727 :
1728 : /************************************************************************/
1729 : /* UnMarkSuppressOnClose() */
1730 : /************************************************************************/
1731 :
1732 : /** Remove the flag requesting the dataset to be deleted on close. */
1733 1 : void GDALDataset::UnMarkSuppressOnClose()
1734 : {
1735 1 : bSuppressOnClose = false;
1736 1 : }
1737 :
1738 : /************************************************************************/
1739 : /* CleanupPostFileClosing() */
1740 : /************************************************************************/
1741 :
1742 : /** This method should be called by driver implementations in their destructor,
1743 : * after having closed all files, but before having freed resources that
1744 : * are needed for their GetFileList() implementation.
1745 : * This is used to implement MarkSuppressOnClose behavior.
1746 : */
1747 245 : void GDALDataset::CleanupPostFileClosing()
1748 : {
1749 245 : if (IsMarkedSuppressOnClose())
1750 : {
1751 1 : char **papszFileList = GetFileList();
1752 3 : for (int i = 0; papszFileList && papszFileList[i]; ++i)
1753 2 : VSIUnlink(papszFileList[i]);
1754 1 : CSLDestroy(papszFileList);
1755 : }
1756 245 : }
1757 :
1758 : /************************************************************************/
1759 : /* GetGCPCount() */
1760 : /************************************************************************/
1761 :
1762 : /**
1763 : * \brief Get number of GCPs.
1764 : *
1765 : * This method is the same as the C function GDALGetGCPCount().
1766 : *
1767 : * @return number of GCPs for this dataset. Zero if there are none.
1768 : */
1769 :
1770 10748 : int GDALDataset::GetGCPCount()
1771 : {
1772 10748 : return 0;
1773 : }
1774 :
1775 : /************************************************************************/
1776 : /* GDALGetGCPCount() */
1777 : /************************************************************************/
1778 :
1779 : /**
1780 : * \brief Get number of GCPs.
1781 : *
1782 : * @see GDALDataset::GetGCPCount()
1783 : */
1784 :
1785 596 : int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1786 :
1787 : {
1788 596 : VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1789 :
1790 596 : return GDALDataset::FromHandle(hDS)->GetGCPCount();
1791 : }
1792 :
1793 : /************************************************************************/
1794 : /* GetGCPProjection() */
1795 : /************************************************************************/
1796 :
1797 : /**
1798 : * \brief Get output projection for GCPs.
1799 : *
1800 : * This method is the same as the C function GDALGetGCPProjection().
1801 : *
1802 : * The projection string follows the normal rules from GetProjectionRef().
1803 : *
1804 : * \note Starting with GDAL 3.0, this is a compatibility layer around
1805 : * GetGCPSpatialRef()
1806 : *
1807 : * @return internal projection string or "" if there are no GCPs.
1808 : * It should not be altered, freed or expected to last for long.
1809 : */
1810 :
1811 371 : const char *GDALDataset::GetGCPProjection()
1812 : {
1813 371 : const auto poSRS = GetGCPSpatialRef();
1814 371 : if (!poSRS || !m_poPrivate)
1815 : {
1816 228 : return "";
1817 : }
1818 143 : char *pszWKT = nullptr;
1819 143 : poSRS->exportToWkt(&pszWKT);
1820 143 : if (!pszWKT)
1821 : {
1822 0 : return "";
1823 : }
1824 143 : if (m_poPrivate->m_pszWKTGCPCached &&
1825 57 : strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
1826 : {
1827 57 : CPLFree(pszWKT);
1828 57 : return m_poPrivate->m_pszWKTGCPCached;
1829 : }
1830 86 : CPLFree(m_poPrivate->m_pszWKTGCPCached);
1831 86 : m_poPrivate->m_pszWKTGCPCached = pszWKT;
1832 86 : return m_poPrivate->m_pszWKTGCPCached;
1833 : }
1834 :
1835 : /************************************************************************/
1836 : /* GetGCPSpatialRef() */
1837 : /************************************************************************/
1838 :
1839 : /**
1840 : * \brief Get output spatial reference system for GCPs.
1841 : *
1842 : * Same as the C function GDALGetGCPSpatialRef().
1843 : *
1844 : * When a SRS is not available, null is returned. If used on
1845 : * a dataset where there is a geotransform, and not GCPs, this method returns
1846 : * null. Use GetSpatialRef() instead.
1847 : *
1848 : * @since GDAL 3.0
1849 : *
1850 : * @return a pointer to an internal object. It should not be altered or freed.
1851 : * Its lifetime will be the one of the dataset object, or until the next
1852 : * call to this method.
1853 : */
1854 :
1855 37 : const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
1856 : {
1857 37 : return nullptr;
1858 : }
1859 :
1860 : /************************************************************************/
1861 : /* GDALGetGCPSpatialRef() */
1862 : /************************************************************************/
1863 :
1864 : /**
1865 : * \brief Get output spatial reference system for GCPs.
1866 : *
1867 : * @since GDAL 3.0
1868 : *
1869 : * @see GDALDataset::GetGCPSpatialRef()
1870 : */
1871 :
1872 60 : OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
1873 :
1874 : {
1875 60 : VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1876 :
1877 60 : return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1878 60 : GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
1879 : }
1880 :
1881 : /************************************************************************/
1882 : /* GDALGetGCPProjection() */
1883 : /************************************************************************/
1884 :
1885 : /**
1886 : * \brief Get output projection for GCPs.
1887 : *
1888 : * @see GDALDataset::GetGCPProjection()
1889 : */
1890 :
1891 305 : const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
1892 :
1893 : {
1894 305 : VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1895 :
1896 305 : return GDALDataset::FromHandle(hDS)->GetGCPProjection();
1897 : }
1898 :
1899 : /************************************************************************/
1900 : /* GetGCPs() */
1901 : /************************************************************************/
1902 :
1903 : /**
1904 : * \brief Fetch GCPs.
1905 : *
1906 : * This method is the same as the C function GDALGetGCPs().
1907 : *
1908 : * @return pointer to internal GCP structure list. It should not be modified,
1909 : * and may change on the next GDAL call.
1910 : */
1911 :
1912 10 : const GDAL_GCP *GDALDataset::GetGCPs()
1913 : {
1914 10 : return nullptr;
1915 : }
1916 :
1917 : /************************************************************************/
1918 : /* GDALGetGCPs() */
1919 : /************************************************************************/
1920 :
1921 : /**
1922 : * \brief Fetch GCPs.
1923 : *
1924 : * @see GDALDataset::GetGCPs()
1925 : */
1926 :
1927 154 : const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
1928 :
1929 : {
1930 154 : VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
1931 :
1932 154 : return GDALDataset::FromHandle(hDS)->GetGCPs();
1933 : }
1934 :
1935 : /************************************************************************/
1936 : /* SetGCPs() */
1937 : /************************************************************************/
1938 :
1939 : /**
1940 : * \brief Assign GCPs.
1941 : *
1942 : * This method is the same as the C function GDALSetGCPs().
1943 : *
1944 : * This method assigns the passed set of GCPs to this dataset, as well as
1945 : * setting their coordinate system. Internally copies are made of the
1946 : * coordinate system and list of points, so the caller remains responsible for
1947 : * deallocating these arguments if appropriate.
1948 : *
1949 : * Most formats do not support setting of GCPs, even formats that can
1950 : * handle GCPs. These formats will return CE_Failure.
1951 : *
1952 : * \note Startig with GDAL 3.0, this is a compatibility layer around
1953 : * SetGCPs(int, const GDAL_GCP*, const char*)
1954 : *
1955 : * @param nGCPCount number of GCPs being assigned.
1956 : *
1957 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1958 : *
1959 : * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
1960 : * GCP output coordinates. This parameter should be "" if no output coordinate
1961 : * system is known.
1962 : *
1963 : * @return CE_None on success, CE_Failure on failure (including if action is
1964 : * not supported for this format).
1965 : */
1966 :
1967 52 : CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
1968 : const char *pszGCPProjection)
1969 :
1970 : {
1971 52 : if (pszGCPProjection && pszGCPProjection[0] != '\0')
1972 : {
1973 70 : OGRSpatialReference oSRS;
1974 35 : oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1975 35 : if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
1976 : {
1977 0 : return CE_Failure;
1978 : }
1979 35 : return SetGCPs(nGCPCount, pasGCPList, &oSRS);
1980 : }
1981 : else
1982 : {
1983 17 : return SetGCPs(nGCPCount, pasGCPList,
1984 17 : static_cast<const OGRSpatialReference *>(nullptr));
1985 : }
1986 : }
1987 :
1988 : /************************************************************************/
1989 : /* SetGCPs() */
1990 : /************************************************************************/
1991 :
1992 : /**
1993 : * \brief Assign GCPs.
1994 : *
1995 : * This method is the same as the C function GDALSetGCPs().
1996 : *
1997 : * This method assigns the passed set of GCPs to this dataset, as well as
1998 : * setting their coordinate system. Internally copies are made of the
1999 : * coordinate system and list of points, so the caller remains responsible for
2000 : * deallocating these arguments if appropriate.
2001 : *
2002 : * Most formats do not support setting of GCPs, even formats that can
2003 : * handle GCPs. These formats will return CE_Failure.
2004 : *
2005 : * @since GDAL 3.0
2006 : *
2007 : * @param nGCPCount number of GCPs being assigned.
2008 : *
2009 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2010 : *
2011 : * @param poGCP_SRS the new coordinate reference system to assign for the
2012 : * GCP output coordinates. This parameter should be null if no output
2013 : * coordinate system is known.
2014 : *
2015 : * @return CE_None on success, CE_Failure on failure (including if action is
2016 : * not supported for this format).
2017 : */
2018 :
2019 0 : CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2020 : CPL_UNUSED const GDAL_GCP *pasGCPList,
2021 : CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2022 :
2023 : {
2024 0 : if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2025 0 : ReportError(CE_Failure, CPLE_NotSupported,
2026 : "Dataset does not support the SetGCPs() method.");
2027 :
2028 0 : return CE_Failure;
2029 : }
2030 :
2031 : /************************************************************************/
2032 : /* GDALSetGCPs() */
2033 : /************************************************************************/
2034 :
2035 : /**
2036 : * \brief Assign GCPs.
2037 : *
2038 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
2039 : */
2040 :
2041 31 : CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2042 : const GDAL_GCP *pasGCPList,
2043 : const char *pszGCPProjection)
2044 :
2045 : {
2046 31 : VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2047 :
2048 31 : return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2049 31 : pszGCPProjection);
2050 : }
2051 :
2052 : /************************************************************************/
2053 : /* GDALSetGCPs2() */
2054 : /************************************************************************/
2055 :
2056 : /**
2057 : * \brief Assign GCPs.
2058 : *
2059 : * @since GDAL 3.0
2060 : * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
2061 : */
2062 :
2063 6 : CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
2064 : OGRSpatialReferenceH hSRS)
2065 :
2066 : {
2067 6 : VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
2068 :
2069 12 : return GDALDataset::FromHandle(hDS)->SetGCPs(
2070 6 : nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
2071 : }
2072 :
2073 : /************************************************************************/
2074 : /* BuildOverviews() */
2075 : /************************************************************************/
2076 :
2077 : /**
2078 : * \brief Build raster overview(s)
2079 : *
2080 : * If the operation is unsupported for the indicated dataset, then
2081 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
2082 : * CPLE_NotSupported.
2083 : *
2084 : * Depending on the actual file format, all overviews level can be also
2085 : * deleted by specifying nOverviews == 0. This works at least for external
2086 : * overviews (.ovr), TIFF internal overviews, etc.
2087 : *
2088 : * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
2089 : * to "ALL_CPUS" or a integer value to specify the number of threads to use for
2090 : * overview computation.
2091 : *
2092 : * This method is the same as the C function GDALBuildOverviewsEx().
2093 : *
2094 : * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
2095 : * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
2096 : * or "NONE" controlling the downsampling method applied.
2097 : * @param nOverviews number of overviews to build, or 0 to clean overviews.
2098 : * @param panOverviewList the list of overview decimation factors to build, or
2099 : * NULL if nOverviews == 0.
2100 : * @param nListBands number of bands to build overviews for in panBandList.
2101 : * Build for all bands if this is 0.
2102 : * @param panBandList list of band numbers.
2103 : * @param pfnProgress a function to call to report progress, or NULL.
2104 : * @param pProgressData application data to pass to the progress function.
2105 : * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
2106 : * key=value pairs, or NULL
2107 : *
2108 : * @return CE_None on success or CE_Failure if the operation doesn't work.
2109 : *
2110 : * For example, to build overview level 2, 4 and 8 on all bands the following
2111 : * call could be made:
2112 : * \code{.cpp}
2113 : * int anOverviewList[3] = { 2, 4, 8 };
2114 : *
2115 : * poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
2116 : * GDALDummyProgress, nullptr );
2117 : * \endcode
2118 : *
2119 : * @see GDALRegenerateOverviewsEx()
2120 : */
2121 :
2122 572 : CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
2123 : const int *panOverviewList, int nListBands,
2124 : const int *panBandList,
2125 : GDALProgressFunc pfnProgress,
2126 : void *pProgressData,
2127 : CSLConstList papszOptions)
2128 : {
2129 572 : int *panAllBandList = nullptr;
2130 :
2131 572 : if (nListBands == 0)
2132 : {
2133 561 : nListBands = GetRasterCount();
2134 : panAllBandList =
2135 561 : static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2136 1510 : for (int i = 0; i < nListBands; ++i)
2137 949 : panAllBandList[i] = i + 1;
2138 :
2139 561 : panBandList = panAllBandList;
2140 : }
2141 :
2142 572 : if (pfnProgress == nullptr)
2143 540 : pfnProgress = GDALDummyProgress;
2144 :
2145 : // At time of writing, all overview generation options are actually
2146 : // expected to be passed as configuration options.
2147 572 : std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;
2148 605 : for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(papszOptions))
2149 : {
2150 : apoConfigOptionSetter.emplace_back(
2151 33 : std::make_unique<CPLConfigOptionSetter>(pszKey, pszValue, false));
2152 : }
2153 :
2154 : const CPLErr eErr =
2155 1144 : IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
2156 572 : panBandList, pfnProgress, pProgressData, papszOptions);
2157 :
2158 572 : if (panAllBandList != nullptr)
2159 560 : CPLFree(panAllBandList);
2160 :
2161 1144 : return eErr;
2162 : }
2163 :
2164 : /************************************************************************/
2165 : /* GDALBuildOverviews() */
2166 : /************************************************************************/
2167 :
2168 : /**
2169 : * \brief Build raster overview(s)
2170 : *
2171 : * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
2172 : */
2173 :
2174 21 : CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
2175 : const char *pszResampling, int nOverviews,
2176 : const int *panOverviewList,
2177 : int nListBands, const int *panBandList,
2178 : GDALProgressFunc pfnProgress,
2179 : void *pProgressData)
2180 :
2181 : {
2182 21 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2183 :
2184 21 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2185 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2186 21 : pfnProgress, pProgressData, nullptr);
2187 : }
2188 :
2189 : /************************************************************************/
2190 : /* GDALBuildOverviews() */
2191 : /************************************************************************/
2192 :
2193 : /**
2194 : * \brief Build raster overview(s)
2195 : *
2196 : * @see GDALDataset::BuildOverviews()
2197 : * @since GDAL 3.6
2198 : */
2199 :
2200 : CPLErr CPL_STDCALL
2201 532 : GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
2202 : int nOverviews, const int *panOverviewList, int nListBands,
2203 : const int *panBandList, GDALProgressFunc pfnProgress,
2204 : void *pProgressData, CSLConstList papszOptions)
2205 :
2206 : {
2207 532 : VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2208 :
2209 532 : return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2210 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2211 532 : pfnProgress, pProgressData, papszOptions);
2212 : }
2213 :
2214 : /************************************************************************/
2215 : /* IBuildOverviews() */
2216 : /* */
2217 : /* Default implementation. */
2218 : /************************************************************************/
2219 :
2220 : //! @cond Doxygen_Suppress
2221 183 : CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
2222 : const int *panOverviewList, int nListBands,
2223 : const int *panBandList,
2224 : GDALProgressFunc pfnProgress,
2225 : void *pProgressData,
2226 : CSLConstList papszOptions)
2227 :
2228 : {
2229 183 : if (oOvManager.IsInitialized())
2230 182 : return oOvManager.BuildOverviews(
2231 : nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2232 182 : panBandList, pfnProgress, pProgressData, papszOptions);
2233 : else
2234 : {
2235 1 : ReportError(CE_Failure, CPLE_NotSupported,
2236 : "BuildOverviews() not supported for this dataset.");
2237 :
2238 1 : return CE_Failure;
2239 : }
2240 : }
2241 :
2242 : //! @endcond
2243 :
2244 : /************************************************************************/
2245 : /* IRasterIO() */
2246 : /* */
2247 : /* The default implementation of IRasterIO() is, in the general */
2248 : /* case to pass the request off to each band objects rasterio */
2249 : /* methods with appropriate arguments. In some cases, it might */
2250 : /* choose instead the BlockBasedRasterIO() implementation. */
2251 : /************************************************************************/
2252 :
2253 : //! @cond Doxygen_Suppress
2254 437099 : CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2255 : int nXSize, int nYSize, void *pData,
2256 : int nBufXSize, int nBufYSize,
2257 : GDALDataType eBufType, int nBandCount,
2258 : int *panBandMap, GSpacing nPixelSpace,
2259 : GSpacing nLineSpace, GSpacing nBandSpace,
2260 : GDALRasterIOExtraArg *psExtraArg)
2261 :
2262 : {
2263 437099 : const char *pszInterleave = nullptr;
2264 :
2265 437099 : CPLAssert(nullptr != pData);
2266 :
2267 437099 : const bool bHasSubpixelShift =
2268 438529 : psExtraArg->bFloatingPointWindowValidity &&
2269 437300 : psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2270 201 : (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2271 :
2272 436999 : if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2273 67966 : nBandCount > 1 &&
2274 67966 : (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2275 874098 : nullptr &&
2276 65145 : EQUAL(pszInterleave, "PIXEL"))
2277 : {
2278 62984 : return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2279 : nBufXSize, nBufYSize, eBufType, nBandCount,
2280 : panBandMap, nPixelSpace, nLineSpace,
2281 62985 : nBandSpace, psExtraArg);
2282 : }
2283 :
2284 374115 : if (eRWFlag == GF_Read &&
2285 199593 : (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2286 199408 : psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2287 199406 : psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2288 199593 : psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2289 353 : !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2290 : {
2291 318 : if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2292 : {
2293 153 : int bTried = FALSE;
2294 153 : const CPLErr eErr = TryOverviewRasterIO(
2295 : eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2296 : nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2297 : nLineSpace, nBandSpace, psExtraArg, &bTried);
2298 153 : if (bTried)
2299 1 : return eErr;
2300 : }
2301 :
2302 317 : GDALDataType eFirstBandDT = GDT_Unknown;
2303 317 : int nFirstMaskFlags = 0;
2304 317 : GDALRasterBand *poFirstMaskBand = nullptr;
2305 317 : int nOKBands = 0;
2306 :
2307 : // Check if bands share the same mask band
2308 1277 : for (int i = 0; i < nBandCount; ++i)
2309 : {
2310 1050 : GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2311 1540 : if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2312 489 : poBand->GetOverviewCount())
2313 : {
2314 : // Could be improved to select the appropriate overview.
2315 3 : break;
2316 : }
2317 1048 : if (poBand->GetColorTable() != nullptr)
2318 : {
2319 0 : break;
2320 : }
2321 1051 : const GDALDataType eDT = poBand->GetRasterDataType();
2322 1050 : if (GDALDataTypeIsComplex(eDT))
2323 : {
2324 30 : break;
2325 : }
2326 1017 : if (i == 0)
2327 : {
2328 283 : eFirstBandDT = eDT;
2329 283 : nFirstMaskFlags = poBand->GetMaskFlags();
2330 286 : if (nFirstMaskFlags == GMF_NODATA)
2331 : {
2332 : // The dataset-level resampling code is not ready for nodata
2333 : // Fallback to band-level resampling
2334 6 : break;
2335 : }
2336 280 : poFirstMaskBand = poBand->GetMaskBand();
2337 : }
2338 : else
2339 : {
2340 734 : if (eDT != eFirstBandDT)
2341 : {
2342 0 : break;
2343 : }
2344 734 : int nMaskFlags = poBand->GetMaskFlags();
2345 737 : if (nMaskFlags == GMF_NODATA)
2346 : {
2347 : // The dataset-level resampling code is not ready for nodata
2348 : // Fallback to band-level resampling
2349 0 : break;
2350 : }
2351 737 : GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2352 735 : if (nFirstMaskFlags == GMF_ALL_VALID &&
2353 : nMaskFlags == GMF_ALL_VALID)
2354 : {
2355 : // Ok.
2356 : }
2357 166 : else if (poFirstMaskBand == poMaskBand)
2358 : {
2359 : // Ok.
2360 : }
2361 : else
2362 : {
2363 55 : break;
2364 : }
2365 : }
2366 :
2367 960 : ++nOKBands;
2368 : }
2369 :
2370 321 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2371 321 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2372 :
2373 321 : CPLErr eErr = CE_None;
2374 321 : if (nOKBands > 0)
2375 : {
2376 280 : if (nOKBands < nBandCount)
2377 : {
2378 55 : psExtraArg->pfnProgress = GDALScaledProgress;
2379 110 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2380 55 : 0.0, static_cast<double>(nOKBands) / nBandCount,
2381 : pfnProgressGlobal, pProgressDataGlobal);
2382 55 : if (psExtraArg->pProgressData == nullptr)
2383 53 : psExtraArg->pfnProgress = nullptr;
2384 : }
2385 :
2386 280 : eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2387 : pData, nBufXSize, nBufYSize, eBufType,
2388 : nOKBands, panBandMap, nPixelSpace,
2389 : nLineSpace, nBandSpace, psExtraArg);
2390 :
2391 280 : if (nOKBands < nBandCount)
2392 : {
2393 55 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2394 : }
2395 : }
2396 321 : if (eErr == CE_None && nOKBands < nBandCount)
2397 : {
2398 92 : if (nOKBands > 0)
2399 : {
2400 53 : psExtraArg->pfnProgress = GDALScaledProgress;
2401 106 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2402 53 : static_cast<double>(nOKBands) / nBandCount, 1.0,
2403 : pfnProgressGlobal, pProgressDataGlobal);
2404 53 : if (psExtraArg->pProgressData == nullptr)
2405 51 : psExtraArg->pfnProgress = nullptr;
2406 : }
2407 184 : eErr = BandBasedRasterIO(
2408 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
2409 92 : static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2410 : nBufYSize, eBufType, nBandCount - nOKBands,
2411 92 : panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2412 : psExtraArg);
2413 92 : if (nOKBands > 0)
2414 : {
2415 53 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2416 : }
2417 : }
2418 :
2419 319 : psExtraArg->pfnProgress = pfnProgressGlobal;
2420 319 : psExtraArg->pProgressData = pProgressDataGlobal;
2421 :
2422 319 : return eErr;
2423 : }
2424 :
2425 373797 : return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2426 : nBufXSize, nBufYSize, eBufType, nBandCount,
2427 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2428 373794 : psExtraArg);
2429 : }
2430 :
2431 : //! @endcond
2432 :
2433 : /************************************************************************/
2434 : /* BandBasedRasterIO() */
2435 : /* */
2436 : /* Pass the request off to each band objects rasterio methods with */
2437 : /* appropriate arguments. */
2438 : /************************************************************************/
2439 :
2440 : //! @cond Doxygen_Suppress
2441 634914 : CPLErr GDALDataset::BandBasedRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2442 : int nXSize, int nYSize, void *pData,
2443 : int nBufXSize, int nBufYSize,
2444 : GDALDataType eBufType, int nBandCount,
2445 : int *panBandMap, GSpacing nPixelSpace,
2446 : GSpacing nLineSpace, GSpacing nBandSpace,
2447 : GDALRasterIOExtraArg *psExtraArg)
2448 :
2449 : {
2450 : int iBandIndex;
2451 634914 : CPLErr eErr = CE_None;
2452 :
2453 634914 : GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2454 634914 : void *pProgressDataGlobal = psExtraArg->pProgressData;
2455 :
2456 1554760 : for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2457 : ++iBandIndex)
2458 : {
2459 919830 : GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2460 :
2461 919836 : if (poBand == nullptr)
2462 : {
2463 0 : eErr = CE_Failure;
2464 0 : break;
2465 : }
2466 :
2467 919836 : GByte *pabyBandData =
2468 919836 : static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2469 :
2470 919836 : if (nBandCount > 1)
2471 : {
2472 419437 : psExtraArg->pfnProgress = GDALScaledProgress;
2473 838871 : psExtraArg->pProgressData = GDALCreateScaledProgress(
2474 : 1.0 * iBandIndex / nBandCount,
2475 419437 : 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2476 : pProgressDataGlobal);
2477 419434 : if (psExtraArg->pProgressData == nullptr)
2478 418764 : psExtraArg->pfnProgress = nullptr;
2479 : }
2480 :
2481 1839690 : eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2482 : pabyBandData, nBufXSize, nBufYSize, eBufType,
2483 919833 : nPixelSpace, nLineSpace, psExtraArg);
2484 :
2485 919856 : if (nBandCount > 1)
2486 419467 : GDALDestroyScaledProgress(psExtraArg->pProgressData);
2487 : }
2488 :
2489 634925 : psExtraArg->pfnProgress = pfnProgressGlobal;
2490 634925 : psExtraArg->pProgressData = pProgressDataGlobal;
2491 :
2492 634925 : return eErr;
2493 : }
2494 :
2495 : //! @endcond
2496 :
2497 : /************************************************************************/
2498 : /* ValidateRasterIOOrAdviseReadParameters() */
2499 : /************************************************************************/
2500 :
2501 : //! @cond Doxygen_Suppress
2502 722753 : CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2503 : const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
2504 : int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
2505 : int nBandCount, int *panBandMap)
2506 : {
2507 :
2508 : /* -------------------------------------------------------------------- */
2509 : /* Some size values are "noop". Lets just return to avoid */
2510 : /* stressing lower level functions. */
2511 : /* -------------------------------------------------------------------- */
2512 722753 : if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2513 : {
2514 14 : CPLDebug("GDAL",
2515 : "%s skipped for odd window or buffer size.\n"
2516 : " Window = (%d,%d)x%dx%d\n"
2517 : " Buffer = %dx%d",
2518 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2519 : nBufYSize);
2520 :
2521 2 : *pbStopProcessingOnCENone = TRUE;
2522 2 : return CE_None;
2523 : }
2524 :
2525 722739 : CPLErr eErr = CE_None;
2526 722739 : *pbStopProcessingOnCENone = FALSE;
2527 :
2528 722739 : if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2529 722733 : nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2530 722735 : nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2531 : {
2532 3 : ReportError(CE_Failure, CPLE_IllegalArg,
2533 : "Access window out of range in %s. Requested "
2534 : "(%d,%d) of size %dx%d on raster of %dx%d.",
2535 : pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2536 : nRasterYSize);
2537 2 : eErr = CE_Failure;
2538 : }
2539 :
2540 722738 : if (panBandMap == nullptr && nBandCount > GetRasterCount())
2541 : {
2542 0 : ReportError(CE_Failure, CPLE_IllegalArg,
2543 : "%s: nBandCount cannot be greater than %d", pszCallingFunc,
2544 : GetRasterCount());
2545 0 : eErr = CE_Failure;
2546 : }
2547 :
2548 1950090 : for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2549 : {
2550 1227350 : int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2551 1227350 : if (iBand < 1 || iBand > GetRasterCount())
2552 : {
2553 3 : ReportError(
2554 : CE_Failure, CPLE_IllegalArg,
2555 : "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2556 : pszCallingFunc, i, iBand);
2557 3 : eErr = CE_Failure;
2558 : }
2559 :
2560 1227350 : if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
2561 : {
2562 0 : ReportError(
2563 : CE_Failure, CPLE_IllegalArg,
2564 : "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2565 : pszCallingFunc, i, iBand);
2566 0 : eErr = CE_Failure;
2567 : }
2568 : }
2569 :
2570 722738 : return eErr;
2571 : }
2572 :
2573 : //! @endcond
2574 :
2575 : /************************************************************************/
2576 : /* RasterIO() */
2577 : /************************************************************************/
2578 :
2579 : /**
2580 : * \brief Read/write a region of image data from multiple bands.
2581 : *
2582 : * This method allows reading a region of one or more GDALRasterBands from
2583 : * this dataset into a buffer, or writing data from a buffer into a region
2584 : * of the GDALRasterBands. It automatically takes care of data type
2585 : * translation if the data type (eBufType) of the buffer is different than
2586 : * that of the GDALRasterBand.
2587 : * The method also takes care of image decimation / replication if the
2588 : * buffer size (nBufXSize x nBufYSize) is different than the size of the
2589 : * region being accessed (nXSize x nYSize).
2590 : *
2591 : * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2592 : * writing from various organization of buffers.
2593 : *
2594 : * Some formats may efficiently implement decimation into a buffer by
2595 : * reading from lower resolution overview images. The logic of the default
2596 : * implementation in the base class GDALRasterBand is the following one. It
2597 : * computes a target_downscaling_factor from the window of interest and buffer
2598 : * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
2599 : * It then walks through overviews and will select the first one whose
2600 : * downscaling factor is greater than target_downscaling_factor / 1.2.
2601 : *
2602 : * Let's assume we have overviews at downscaling factors 2, 4 and 8.
2603 : * The relationship between target_downscaling_factor and the select overview
2604 : * level is the following one:
2605 : *
2606 : * target_downscaling_factor | selected_overview
2607 : * ------------------------- | -----------------
2608 : * ]0, 2 / 1.2] | full resolution band
2609 : * ]2 / 1.2, 4 / 1.2] | 2x downsampled band
2610 : * ]4 / 1.2, 8 / 1.2] | 4x downsampled band
2611 : * ]8 / 1.2, infinity[ | 8x downsampled band
2612 : *
2613 : * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
2614 : * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
2615 : * option. Also note that starting with GDAL 3.9, when the resampling algorithm
2616 : * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
2617 : * this oversampling threshold defaults to 1. Consequently if there are overviews
2618 : * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
2619 : * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
2620 : *
2621 : * For highest performance full resolution data access, read and write
2622 : * on "block boundaries" as returned by GetBlockSize(), or use the
2623 : * ReadBlock() and WriteBlock() methods.
2624 : *
2625 : * This method is the same as the C GDALDatasetRasterIO() or
2626 : * GDALDatasetRasterIOEx() functions.
2627 : *
2628 : * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2629 : * write a region of data.
2630 : *
2631 : * @param nXOff The pixel offset to the top left corner of the region
2632 : * of the band to be accessed. This would be zero to start from the left side.
2633 : *
2634 : * @param nYOff The line offset to the top left corner of the region
2635 : * of the band to be accessed. This would be zero to start from the top.
2636 : *
2637 : * @param nXSize The width of the region of the band to be accessed in pixels.
2638 : *
2639 : * @param nYSize The height of the region of the band to be accessed in lines.
2640 : *
2641 : * @param pData The buffer into which the data should be read, or from which
2642 : * it should be written. This buffer must contain at least
2643 : * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized
2644 : * in left to right,top to bottom pixel order. Spacing is controlled by the
2645 : * nPixelSpace, and nLineSpace parameters.
2646 : * Note that even with eRWFlag==GF_Write, the content of the buffer might be
2647 : * temporarily modified during the execution of this method (and eventually
2648 : * restored back to its original content), so it is not safe to use a buffer
2649 : * stored in a read-only section of the calling program.
2650 : *
2651 : * @param nBufXSize the width of the buffer image into which the desired region
2652 : * is to be read, or from which it is to be written.
2653 : *
2654 : * @param nBufYSize the height of the buffer image into which the desired
2655 : * region is to be read, or from which it is to be written.
2656 : *
2657 : * @param eBufType the type of the pixel values in the pData data buffer. The
2658 : * pixel values will automatically be translated to/from the GDALRasterBand
2659 : * data type as needed.
2660 : *
2661 : * @param nBandCount the number of bands being read or written.
2662 : *
2663 : * @param panBandMap the list of nBandCount band numbers being read/written.
2664 : * Note band numbers are 1 based. This may be NULL to select the first
2665 : * nBandCount bands.
2666 : *
2667 : * @param nPixelSpace The byte offset from the start of one pixel value in
2668 : * pData to the start of the next pixel value within a scanline. If defaulted
2669 : * (0) the size of the datatype eBufType is used.
2670 : *
2671 : * @param nLineSpace The byte offset from the start of one scanline in
2672 : * pData to the start of the next. If defaulted (0) the size of the datatype
2673 : * eBufType * nBufXSize is used.
2674 : *
2675 : * @param nBandSpace the byte offset from the start of one bands data to the
2676 : * start of the next. If defaulted (0) the value will be
2677 : * nLineSpace * nBufYSize implying band sequential organization
2678 : * of the data buffer.
2679 : *
2680 : * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
2681 : * structure with additional arguments to specify resampling and progress
2682 : * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
2683 : * configuration option can also be defined to override the default resampling
2684 : * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
2685 : *
2686 : * @return CE_Failure if the access fails, otherwise CE_None.
2687 : */
2688 :
2689 710403 : CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2690 : int nXSize, int nYSize, void *pData, int nBufXSize,
2691 : int nBufYSize, GDALDataType eBufType,
2692 : int nBandCount, int *panBandMap,
2693 : GSpacing nPixelSpace, GSpacing nLineSpace,
2694 : GSpacing nBandSpace,
2695 : GDALRasterIOExtraArg *psExtraArg)
2696 :
2697 : {
2698 : GDALRasterIOExtraArg sExtraArg;
2699 710403 : if (psExtraArg == nullptr)
2700 : {
2701 526384 : INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2702 :
2703 : // 4 below inits are not strictly needed but make Coverity Scan
2704 : // happy
2705 526384 : sExtraArg.dfXOff = nXOff;
2706 526384 : sExtraArg.dfYOff = nYOff;
2707 526384 : sExtraArg.dfXSize = nXSize;
2708 526384 : sExtraArg.dfYSize = nYSize;
2709 :
2710 526384 : psExtraArg = &sExtraArg;
2711 : }
2712 184019 : else if (psExtraArg->nVersion != RASTERIO_EXTRA_ARG_CURRENT_VERSION)
2713 : {
2714 0 : ReportError(CE_Failure, CPLE_AppDefined,
2715 : "Unhandled version of GDALRasterIOExtraArg");
2716 0 : return CE_Failure;
2717 : }
2718 :
2719 710403 : GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2720 : nBufYSize);
2721 :
2722 710387 : if (nullptr == pData)
2723 : {
2724 0 : ReportError(CE_Failure, CPLE_AppDefined,
2725 : "The buffer into which the data should be read is null");
2726 0 : return CE_Failure;
2727 : }
2728 :
2729 : /* -------------------------------------------------------------------- */
2730 : /* Do some validation of parameters. */
2731 : /* -------------------------------------------------------------------- */
2732 :
2733 710387 : if (eRWFlag != GF_Read && eRWFlag != GF_Write)
2734 : {
2735 0 : ReportError(
2736 : CE_Failure, CPLE_IllegalArg,
2737 : "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
2738 : eRWFlag);
2739 0 : return CE_Failure;
2740 : }
2741 :
2742 710387 : if (eRWFlag == GF_Write)
2743 : {
2744 209856 : if (eAccess != GA_Update)
2745 : {
2746 1 : ReportError(CE_Failure, CPLE_AppDefined,
2747 : "Write operation not permitted on dataset opened "
2748 : "in read-only mode");
2749 1 : return CE_Failure;
2750 : }
2751 : }
2752 :
2753 710386 : int bStopProcessing = FALSE;
2754 710386 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2755 : "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2756 : nBufYSize, nBandCount, panBandMap);
2757 710397 : if (eErr != CE_None || bStopProcessing)
2758 15 : return eErr;
2759 :
2760 : /* -------------------------------------------------------------------- */
2761 : /* If pixel and line spacing are defaulted assign reasonable */
2762 : /* value assuming a packed buffer. */
2763 : /* -------------------------------------------------------------------- */
2764 710382 : if (nPixelSpace == 0)
2765 411730 : nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2766 :
2767 710385 : if (nLineSpace == 0)
2768 : {
2769 514823 : nLineSpace = nPixelSpace * nBufXSize;
2770 : }
2771 :
2772 710385 : if (nBandSpace == 0 && nBandCount > 1)
2773 : {
2774 64687 : nBandSpace = nLineSpace * nBufYSize;
2775 : }
2776 :
2777 710385 : bool bNeedToFreeBandMap = false;
2778 710385 : int anBandMap[] = {1, 2, 3, 4};
2779 710385 : if (panBandMap == nullptr)
2780 : {
2781 350026 : if (nBandCount > 4)
2782 : {
2783 : panBandMap =
2784 58 : static_cast<int *>(VSIMalloc2(sizeof(int), nBandCount));
2785 58 : if (panBandMap == nullptr)
2786 : {
2787 0 : ReportError(CE_Failure, CPLE_OutOfMemory,
2788 : "Out of memory while allocating band map array");
2789 0 : return CE_Failure;
2790 : }
2791 :
2792 740 : for (int i = 0; i < nBandCount; ++i)
2793 682 : panBandMap[i] = i + 1;
2794 :
2795 58 : bNeedToFreeBandMap = true;
2796 : }
2797 : else
2798 : {
2799 349968 : panBandMap = anBandMap;
2800 : }
2801 : }
2802 :
2803 710385 : int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2804 :
2805 : /* -------------------------------------------------------------------- */
2806 : /* We are being forced to use cached IO instead of a driver */
2807 : /* specific implementation. */
2808 : /* -------------------------------------------------------------------- */
2809 710385 : if (bForceCachedIO)
2810 : {
2811 7 : eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2812 : nBufXSize, nBufYSize, eBufType, nBandCount,
2813 : panBandMap, nPixelSpace, nLineSpace,
2814 : nBandSpace, psExtraArg);
2815 : }
2816 :
2817 : /* -------------------------------------------------------------------- */
2818 : /* Call the format specific function. */
2819 : /* -------------------------------------------------------------------- */
2820 : else
2821 : {
2822 710392 : eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2823 : nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap,
2824 710378 : nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
2825 : }
2826 :
2827 710399 : if (bCallLeaveReadWrite)
2828 398097 : LeaveReadWrite();
2829 :
2830 : /* -------------------------------------------------------------------- */
2831 : /* Cleanup */
2832 : /* -------------------------------------------------------------------- */
2833 710399 : if (bNeedToFreeBandMap)
2834 58 : CPLFree(panBandMap);
2835 :
2836 710398 : return eErr;
2837 : }
2838 :
2839 : /************************************************************************/
2840 : /* GDALDatasetRasterIO() */
2841 : /************************************************************************/
2842 :
2843 : /**
2844 : * \brief Read/write a region of image data from multiple bands.
2845 : *
2846 : * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
2847 : * resolution, progress callback, etc. are needed)
2848 : *
2849 : * @see GDALDataset::RasterIO()
2850 : */
2851 :
2852 4100 : CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
2853 : int nXOff, int nYOff, int nXSize,
2854 : int nYSize, void *pData, int nBufXSize,
2855 : int nBufYSize, GDALDataType eBufType,
2856 : int nBandCount, int *panBandMap,
2857 : int nPixelSpace, int nLineSpace,
2858 : int nBandSpace)
2859 :
2860 : {
2861 4100 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
2862 :
2863 4100 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2864 :
2865 4100 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2866 : nBufXSize, nBufYSize, eBufType, nBandCount,
2867 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2868 4100 : nullptr);
2869 : }
2870 :
2871 : /************************************************************************/
2872 : /* GDALDatasetRasterIOEx() */
2873 : /************************************************************************/
2874 :
2875 : /**
2876 : * \brief Read/write a region of image data from multiple bands.
2877 : *
2878 : * @see GDALDataset::RasterIO()
2879 : * @since GDAL 2.0
2880 : */
2881 :
2882 348695 : CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
2883 : GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
2884 : int nYSize, void *pData, int nBufXSize, int nBufYSize,
2885 : GDALDataType eBufType, int nBandCount, int *panBandMap,
2886 : GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
2887 : GDALRasterIOExtraArg *psExtraArg)
2888 :
2889 : {
2890 348695 : VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
2891 :
2892 348695 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2893 :
2894 348695 : return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2895 : nBufXSize, nBufYSize, eBufType, nBandCount,
2896 : panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2897 348695 : psExtraArg);
2898 : }
2899 :
2900 : /************************************************************************/
2901 : /* GetOpenDatasets() */
2902 : /************************************************************************/
2903 :
2904 : /**
2905 : * \brief Fetch all open GDAL dataset handles.
2906 : *
2907 : * This method is the same as the C function GDALGetOpenDatasets().
2908 : *
2909 : * NOTE: This method is not thread safe. The returned list may change
2910 : * at any time and it should not be freed.
2911 : *
2912 : * @param pnCount integer into which to place the count of dataset pointers
2913 : * being returned.
2914 : *
2915 : * @return a pointer to an array of dataset handles.
2916 : */
2917 :
2918 1722 : GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
2919 :
2920 : {
2921 3444 : CPLMutexHolderD(&hDLMutex);
2922 :
2923 1722 : if (poAllDatasetMap == nullptr)
2924 : {
2925 1698 : *pnCount = 0;
2926 1698 : return nullptr;
2927 : }
2928 :
2929 24 : *pnCount = static_cast<int>(poAllDatasetMap->size());
2930 24 : ppDatasets = static_cast<GDALDataset **>(
2931 24 : CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
2932 24 : std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
2933 660 : for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
2934 636 : ppDatasets[i] = oIter->first;
2935 24 : return ppDatasets;
2936 : }
2937 :
2938 : /************************************************************************/
2939 : /* GDALGetOpenDatasets() */
2940 : /************************************************************************/
2941 :
2942 : /**
2943 : * \brief Fetch all open GDAL dataset handles.
2944 : *
2945 : * @see GDALDataset::GetOpenDatasets()
2946 : */
2947 :
2948 0 : void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
2949 :
2950 : {
2951 0 : VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
2952 0 : VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
2953 :
2954 0 : *ppahDSList =
2955 0 : reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
2956 : }
2957 :
2958 : /************************************************************************/
2959 : /* GDALCleanOpenDatasetsList() */
2960 : /************************************************************************/
2961 :
2962 : // Useful when called from the child of a fork(), to avoid closing
2963 : // the datasets of the parent at the child termination.
2964 0 : void GDALNullifyOpenDatasetsList()
2965 : {
2966 0 : poAllDatasetMap = nullptr;
2967 0 : phSharedDatasetSet = nullptr;
2968 0 : ppDatasets = nullptr;
2969 0 : hDLMutex = nullptr;
2970 0 : }
2971 :
2972 : /************************************************************************/
2973 : /* GDALGetAccess() */
2974 : /************************************************************************/
2975 :
2976 : /**
2977 : * \brief Return access flag
2978 : *
2979 : * @see GDALDataset::GetAccess()
2980 : */
2981 :
2982 0 : int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
2983 : {
2984 0 : VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
2985 :
2986 0 : return GDALDataset::FromHandle(hDS)->GetAccess();
2987 : }
2988 :
2989 : /************************************************************************/
2990 : /* AdviseRead() */
2991 : /************************************************************************/
2992 :
2993 : /**
2994 : * \brief Advise driver of upcoming read requests.
2995 : *
2996 : * Some GDAL drivers operate more efficiently if they know in advance what
2997 : * set of upcoming read requests will be made. The AdviseRead() method allows
2998 : * an application to notify the driver of the region and bands of interest,
2999 : * and at what resolution the region will be read.
3000 : *
3001 : * Many drivers just ignore the AdviseRead() call, but it can dramatically
3002 : * accelerate access via some drivers.
3003 : *
3004 : * Depending on call paths, drivers might receive several calls to
3005 : * AdviseRead() with the same parameters.
3006 : *
3007 : * @param nXOff The pixel offset to the top left corner of the region
3008 : * of the band to be accessed. This would be zero to start from the left side.
3009 : *
3010 : * @param nYOff The line offset to the top left corner of the region
3011 : * of the band to be accessed. This would be zero to start from the top.
3012 : *
3013 : * @param nXSize The width of the region of the band to be accessed in pixels.
3014 : *
3015 : * @param nYSize The height of the region of the band to be accessed in lines.
3016 : *
3017 : * @param nBufXSize the width of the buffer image into which the desired region
3018 : * is to be read, or from which it is to be written.
3019 : *
3020 : * @param nBufYSize the height of the buffer image into which the desired
3021 : * region is to be read, or from which it is to be written.
3022 : *
3023 : * @param eBufType the type of the pixel values in the pData data buffer. The
3024 : * pixel values will automatically be translated to/from the GDALRasterBand
3025 : * data type as needed.
3026 : *
3027 : * @param nBandCount the number of bands being read or written.
3028 : *
3029 : * @param panBandMap the list of nBandCount band numbers being read/written.
3030 : * Note band numbers are 1 based. This may be NULL to select the first
3031 : * nBandCount bands.
3032 : *
3033 : * @param papszOptions a list of name=value strings with special control
3034 : * options. Normally this is NULL.
3035 : *
3036 : * @return CE_Failure if the request is invalid and CE_None if it works or
3037 : * is ignored.
3038 : */
3039 :
3040 12102 : CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
3041 : int nBufXSize, int nBufYSize,
3042 : GDALDataType eBufType, int nBandCount,
3043 : int *panBandMap, char **papszOptions)
3044 :
3045 : {
3046 : /* -------------------------------------------------------------------- */
3047 : /* Do some validation of parameters. */
3048 : /* -------------------------------------------------------------------- */
3049 12102 : int bStopProcessing = FALSE;
3050 12102 : CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3051 : "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3052 : nBufXSize, nBufYSize, nBandCount, panBandMap);
3053 12102 : if (eErr != CE_None || bStopProcessing)
3054 0 : return eErr;
3055 :
3056 53657 : for (int iBand = 0; iBand < nBandCount; ++iBand)
3057 : {
3058 41555 : GDALRasterBand *poBand = nullptr;
3059 :
3060 41555 : if (panBandMap == nullptr)
3061 40341 : poBand = GetRasterBand(iBand + 1);
3062 : else
3063 1214 : poBand = GetRasterBand(panBandMap[iBand]);
3064 :
3065 41555 : if (poBand == nullptr)
3066 0 : return CE_Failure;
3067 :
3068 83110 : eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3069 41555 : nBufYSize, eBufType, papszOptions);
3070 :
3071 41555 : if (eErr != CE_None)
3072 0 : return eErr;
3073 : }
3074 :
3075 12102 : return CE_None;
3076 : }
3077 :
3078 : /************************************************************************/
3079 : /* GDALDatasetAdviseRead() */
3080 : /************************************************************************/
3081 :
3082 : /**
3083 : * \brief Advise driver of upcoming read requests.
3084 : *
3085 : * @see GDALDataset::AdviseRead()
3086 : */
3087 1 : CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
3088 : int nXSize, int nYSize, int nBufXSize,
3089 : int nBufYSize, GDALDataType eDT,
3090 : int nBandCount, int *panBandMap,
3091 : CSLConstList papszOptions)
3092 :
3093 : {
3094 1 : VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
3095 :
3096 2 : return GDALDataset::FromHandle(hDS)->AdviseRead(
3097 : nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
3098 1 : panBandMap, const_cast<char **>(papszOptions));
3099 : }
3100 :
3101 : /************************************************************************/
3102 : /* GDALAntiRecursionStruct */
3103 : /************************************************************************/
3104 :
3105 : // Prevent infinite recursion.
3106 : struct GDALAntiRecursionStruct
3107 : {
3108 : struct DatasetContext
3109 : {
3110 : std::string osFilename;
3111 : int nOpenFlags;
3112 : std::string osAllowedDrivers;
3113 :
3114 65682 : DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3115 : const std::string &osAllowedDriversIn)
3116 65682 : : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3117 65682 : osAllowedDrivers(osAllowedDriversIn)
3118 : {
3119 65680 : }
3120 : };
3121 :
3122 : struct DatasetContextCompare
3123 : {
3124 1071180 : bool operator()(const DatasetContext &lhs,
3125 : const DatasetContext &rhs) const
3126 : {
3127 3128260 : return lhs.osFilename < rhs.osFilename ||
3128 1037740 : (lhs.osFilename == rhs.osFilename &&
3129 1021190 : (lhs.nOpenFlags < rhs.nOpenFlags ||
3130 2040920 : (lhs.nOpenFlags == rhs.nOpenFlags &&
3131 2090040 : lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
3132 : }
3133 : };
3134 :
3135 : std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
3136 : int nRecLevel = 0;
3137 : std::map<std::string, int> m_oMapDepth{};
3138 : };
3139 :
3140 : #ifdef _WIN32
3141 : // Currently thread_local and C++ objects don't work well with DLL on Windows
3142 : static void FreeAntiRecursionOpen(void *pData)
3143 : {
3144 : delete static_cast<GDALAntiRecursionStruct *>(pData);
3145 : }
3146 :
3147 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3148 : {
3149 : static GDALAntiRecursionStruct dummy;
3150 : int bMemoryErrorOccurred = false;
3151 : void *pData =
3152 : CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
3153 : if (bMemoryErrorOccurred)
3154 : {
3155 : return dummy;
3156 : }
3157 : if (pData == nullptr)
3158 : {
3159 : auto pAntiRecursion = new GDALAntiRecursionStruct();
3160 : CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
3161 : FreeAntiRecursionOpen, &bMemoryErrorOccurred);
3162 : if (bMemoryErrorOccurred)
3163 : {
3164 : delete pAntiRecursion;
3165 : return dummy;
3166 : }
3167 : return *pAntiRecursion;
3168 : }
3169 : return *static_cast<GDALAntiRecursionStruct *>(pData);
3170 : }
3171 : #else
3172 : static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
3173 :
3174 118281 : static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3175 : {
3176 118281 : return g_tls_antiRecursion;
3177 : }
3178 : #endif
3179 :
3180 : //! @cond Doxygen_Suppress
3181 52597 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3182 52597 : : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3183 : m_osIdentifier(osIdentifier),
3184 52597 : m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3185 : {
3186 52597 : CPLAssert(!osIdentifier.empty());
3187 52597 : }
3188 :
3189 52597 : GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3190 52597 : const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3191 52597 : : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3192 52597 : m_osIdentifier(osIdentifier.empty()
3193 : ? osIdentifier
3194 26836 : : other.m_osIdentifier + osIdentifier),
3195 52597 : m_nDepth(m_osIdentifier.empty()
3196 52597 : ? 0
3197 79433 : : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3198 : {
3199 52597 : }
3200 :
3201 105194 : GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3202 : {
3203 105194 : if (!m_osIdentifier.empty())
3204 : {
3205 79433 : --m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier];
3206 : }
3207 105194 : }
3208 :
3209 : //! @endcond
3210 :
3211 : /************************************************************************/
3212 : /* GetFileList() */
3213 : /************************************************************************/
3214 :
3215 : /**
3216 : * \brief Fetch files forming dataset.
3217 : *
3218 : * Returns a list of files believed to be part of this dataset. If it returns
3219 : * an empty list of files it means there is believed to be no local file
3220 : * system files associated with the dataset (for instance a virtual dataset).
3221 : * The returned file list is owned by the caller and should be deallocated
3222 : * with CSLDestroy().
3223 : *
3224 : * The returned filenames will normally be relative or absolute paths
3225 : * depending on the path used to originally open the dataset. The strings
3226 : * will be UTF-8 encoded.
3227 : *
3228 : * This method is the same as the C GDALGetFileList() function.
3229 : *
3230 : * @return NULL or a NULL terminated array of file names.
3231 : */
3232 :
3233 4693 : char **GDALDataset::GetFileList()
3234 :
3235 : {
3236 9386 : CPLString osMainFilename = GetDescription();
3237 : VSIStatBufL sStat;
3238 :
3239 4693 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3240 : const GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3241 9386 : std::string());
3242 4693 : auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3243 4693 : if (aosDatasetList.find(datasetCtxt) != aosDatasetList.end())
3244 0 : return nullptr;
3245 :
3246 : /* -------------------------------------------------------------------- */
3247 : /* Is the main filename even a real filesystem object? */
3248 : /* -------------------------------------------------------------------- */
3249 : int bMainFileReal =
3250 4693 : VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3251 :
3252 : /* -------------------------------------------------------------------- */
3253 : /* Form new list. */
3254 : /* -------------------------------------------------------------------- */
3255 4693 : char **papszList = nullptr;
3256 :
3257 4693 : if (bMainFileReal)
3258 4637 : papszList = CSLAddString(papszList, osMainFilename);
3259 :
3260 4693 : if (sAntiRecursion.nRecLevel == 100)
3261 : {
3262 0 : CPLError(CE_Failure, CPLE_AppDefined,
3263 : "GetFileList() called with too many recursion levels");
3264 0 : return papszList;
3265 : }
3266 4693 : ++sAntiRecursion.nRecLevel;
3267 :
3268 : /* -------------------------------------------------------------------- */
3269 : /* Do we have a known overview file? */
3270 : /* -------------------------------------------------------------------- */
3271 4693 : if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3272 : {
3273 63 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3274 63 : char **papszOvrList = oOvManager.poODS->GetFileList();
3275 63 : papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3276 63 : CSLDestroy(papszOvrList);
3277 63 : aosDatasetList.erase(iter);
3278 : }
3279 :
3280 : /* -------------------------------------------------------------------- */
3281 : /* Do we have a known mask file? */
3282 : /* -------------------------------------------------------------------- */
3283 4693 : if (oOvManager.HaveMaskFile())
3284 : {
3285 11 : auto iter = aosDatasetList.insert(datasetCtxt).first;
3286 11 : for (const char *pszFile :
3287 22 : CPLStringList(oOvManager.poMaskDS->GetFileList()))
3288 : {
3289 11 : if (CSLFindString(papszList, pszFile) < 0)
3290 11 : papszList = CSLAddString(papszList, pszFile);
3291 : }
3292 11 : aosDatasetList.erase(iter);
3293 : }
3294 :
3295 4693 : --sAntiRecursion.nRecLevel;
3296 :
3297 4693 : return papszList;
3298 : }
3299 :
3300 : /************************************************************************/
3301 : /* GDALGetFileList() */
3302 : /************************************************************************/
3303 :
3304 : /**
3305 : * \brief Fetch files forming dataset.
3306 : *
3307 : * @see GDALDataset::GetFileList()
3308 : */
3309 :
3310 3928 : char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3311 :
3312 : {
3313 3928 : VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3314 :
3315 3928 : return GDALDataset::FromHandle(hDS)->GetFileList();
3316 : }
3317 :
3318 : /************************************************************************/
3319 : /* CreateMaskBand() */
3320 : /************************************************************************/
3321 :
3322 : /**
3323 : * \brief Adds a mask band to the dataset
3324 : *
3325 : * The default implementation of the CreateMaskBand() method is implemented
3326 : * based on similar rules to the .ovr handling implemented using the
3327 : * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3328 : * be created with the same basename as the original file, and it will have
3329 : * one band.
3330 : * The mask images will be deflate compressed tiled images with the same
3331 : * block size as the original image if possible.
3332 : * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3333 : * level, where xx matches the band number of a band of the main dataset. The
3334 : * value of those items will be the one of the nFlagsIn parameter.
3335 : *
3336 : * Note that if you got a mask band with a previous call to GetMaskBand(), it
3337 : * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3338 : * again.
3339 : *
3340 : * @since GDAL 1.5.0
3341 : *
3342 : * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3343 : * GMF_PER_DATASET will be always set, even if not explicitly
3344 : * specified.
3345 : * @return CE_None on success or CE_Failure on an error.
3346 : *
3347 : * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3348 : * @see GDALRasterBand::CreateMaskBand()
3349 : *
3350 : */
3351 17 : CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
3352 :
3353 : {
3354 17 : if (oOvManager.IsInitialized())
3355 : {
3356 17 : CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3357 17 : if (eErr != CE_None)
3358 0 : return eErr;
3359 :
3360 : // Invalidate existing raster band masks.
3361 45 : for (int i = 0; i < nBands; ++i)
3362 : {
3363 28 : GDALRasterBand *poBand = papoBands[i];
3364 28 : poBand->poMask.reset();
3365 : }
3366 :
3367 17 : return CE_None;
3368 : }
3369 :
3370 0 : ReportError(CE_Failure, CPLE_NotSupported,
3371 : "CreateMaskBand() not supported for this dataset.");
3372 :
3373 0 : return CE_Failure;
3374 : }
3375 :
3376 : /************************************************************************/
3377 : /* GDALCreateDatasetMaskBand() */
3378 : /************************************************************************/
3379 :
3380 : /**
3381 : * \brief Adds a mask band to the dataset
3382 : * @see GDALDataset::CreateMaskBand()
3383 : */
3384 84 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3385 :
3386 : {
3387 84 : VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3388 :
3389 84 : return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3390 : }
3391 :
3392 : /************************************************************************/
3393 : /* GDALOpen() */
3394 : /************************************************************************/
3395 :
3396 : /**
3397 : * \brief Open a raster file as a GDALDataset.
3398 : *
3399 : * This function will try to open the passed file, or virtual dataset
3400 : * name by invoking the Open method of each registered GDALDriver in turn.
3401 : * The first successful open will result in a returned dataset. If all
3402 : * drivers fail then NULL is returned and an error is issued.
3403 : *
3404 : * Several recommendations :
3405 : * <ul>
3406 : * <li>If you open a dataset object with GA_Update access, it is not recommended
3407 : * to open a new dataset on the same underlying file.</li>
3408 : * <li>The returned dataset should only be accessed by one thread at a time. If
3409 : * you want to use it from different threads, you must add all necessary code
3410 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3411 : * as GeoTIFF, maintain internal state variables that are updated each time a
3412 : * new block is read, thus preventing concurrent use.) </li>
3413 : * </ul>
3414 : *
3415 : * For drivers supporting the VSI virtual file API, it is possible to open a
3416 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3417 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3418 : * server (see VSIInstallCurlFileHandler())
3419 : *
3420 : * \sa GDALOpenShared()
3421 : * \sa GDALOpenEx()
3422 : *
3423 : * @param pszFilename the name of the file to access. In the case of
3424 : * exotic drivers this may not refer to a physical file, but instead contain
3425 : * information for the driver on how to access a dataset. It should be in UTF-8
3426 : * encoding.
3427 : *
3428 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
3429 : * drivers support only read only access.
3430 : *
3431 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3432 : * this handle can be cast to a GDALDataset *.
3433 : */
3434 :
3435 23269 : GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3436 :
3437 : {
3438 23269 : const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3439 23269 : const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3440 : GDALDatasetH hDataset =
3441 23269 : GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3442 23266 : return hDataset;
3443 : }
3444 :
3445 : /************************************************************************/
3446 : /* GetSharedDS() */
3447 : /************************************************************************/
3448 :
3449 6483 : static GDALDataset *GetSharedDS(const char *pszFilename,
3450 : unsigned int nOpenFlags,
3451 : const char *const *papszOpenOptions)
3452 : {
3453 12966 : CPLMutexHolderD(&hDLMutex);
3454 :
3455 6483 : if (phSharedDatasetSet != nullptr)
3456 : {
3457 6220 : const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3458 : SharedDatasetCtxt sStruct;
3459 :
3460 6220 : sStruct.nPID = nThisPID;
3461 6220 : sStruct.pszDescription = const_cast<char *>(pszFilename);
3462 6220 : sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3463 : std::string osConcatenatedOpenOptions =
3464 6220 : GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3465 6220 : sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3466 6220 : sStruct.poDS = nullptr;
3467 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3468 6220 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3469 6220 : if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3470 : {
3471 107 : sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3472 : psStruct = static_cast<SharedDatasetCtxt *>(
3473 107 : CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3474 : }
3475 6220 : if (psStruct)
3476 : {
3477 6114 : return psStruct->poDS;
3478 : }
3479 : }
3480 369 : return nullptr;
3481 : }
3482 :
3483 : /************************************************************************/
3484 : /* GDALOpenEx() */
3485 : /************************************************************************/
3486 :
3487 : /**
3488 : * \brief Open a raster or vector file as a GDALDataset.
3489 : *
3490 : * This function will try to open the passed file, or virtual dataset
3491 : * name by invoking the Open method of each registered GDALDriver in turn.
3492 : * The first successful open will result in a returned dataset. If all
3493 : * drivers fail then NULL is returned and an error is issued.
3494 : *
3495 : * Several recommendations :
3496 : * <ul>
3497 : * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3498 : * recommended to open a new dataset on the same underlying file.</li>
3499 : * <li>The returned dataset should only be accessed by one thread at a time. If
3500 : * you want to use it from different threads, you must add all necessary code
3501 : * (mutexes, etc.) to avoid concurrent use of the object. (Some drivers, such
3502 : * as GeoTIFF, maintain internal state variables that are updated each time a
3503 : * new block is read, thus preventing concurrent use.) </li>
3504 : * </ul>
3505 : *
3506 : * For drivers supporting the VSI virtual file API, it is possible to open a
3507 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3508 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3509 : * server (see VSIInstallCurlFileHandler())
3510 : *
3511 : * In order to reduce the need for searches through the operating system
3512 : * file system machinery, it is possible to give an optional list of files with
3513 : * the papszSiblingFiles parameter.
3514 : * This is the list of all files at the same level in the file system as the
3515 : * target file, including the target file. The filenames must not include any
3516 : * path components, are essentially just the output of VSIReadDir() on the
3517 : * parent directory. If the target object does not have filesystem semantics
3518 : * then the file list should be NULL.
3519 : *
3520 : * @param pszFilename the name of the file to access. In the case of
3521 : * exotic drivers this may not refer to a physical file, but instead contain
3522 : * information for the driver on how to access a dataset. It should be in UTF-8
3523 : * encoding.
3524 : *
3525 : * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3526 : * through logical or operator.
3527 : * <ul>
3528 : * <li>Driver kind:
3529 : * <ul>
3530 : * <li>GDAL_OF_RASTER for raster drivers,</li>
3531 : * <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
3532 : * <li>GDAL_OF_VECTOR for vector drivers,</li>
3533 : * <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
3534 : * </ul>
3535 : * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
3536 : * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
3537 : * | GDAL_OF_GNM is implied.</li> <li>Access mode: GDAL_OF_READONLY
3538 : * (exclusive)or GDAL_OF_UPDATE.</li> <li>Shared mode: GDAL_OF_SHARED. If set,
3539 : * it allows the sharing of GDALDataset handles for a dataset with other callers
3540 : * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
3541 : * its list of currently open and shared GDALDataset's, and if the
3542 : * GetDescription() name for one exactly matches the pszFilename passed to
3543 : * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
3544 : * from the same thread.</li> <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
3545 : * a failed attempt to open the file will lead to an error message to be
3546 : * reported.</li>
3547 : * </ul>
3548 : *
3549 : * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3550 : * terminated list of strings with the driver short names that must be
3551 : * considered.
3552 : *
3553 : * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3554 : * options passed to candidate drivers. An option exists for all drivers,
3555 : * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3556 : * The level index starts at 0. The level number can be suffixed by "only" to
3557 : * specify that only this overview level must be visible, and not sub-levels.
3558 : * Open options are validated by default, and a warning is emitted in case the
3559 : * option is not recognized. In some scenarios, it might be not desirable (e.g.
3560 : * when not knowing which driver will open the file), so the special open option
3561 : * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3562 : * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3563 : * that it may not cause a warning if the driver doesn't declare this option.
3564 : * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3565 : * no overviews should be exposed.
3566 : *
3567 : * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3568 : * filenames that are auxiliary to the main filename. If NULL is passed, a
3569 : * probing of the file system will be done.
3570 : *
3571 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
3572 : * this handle can be cast to a GDALDataset *.
3573 : *
3574 : * @since GDAL 2.0
3575 : */
3576 :
3577 67105 : GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
3578 : unsigned int nOpenFlags,
3579 : const char *const *papszAllowedDrivers,
3580 : const char *const *papszOpenOptions,
3581 : const char *const *papszSiblingFiles)
3582 : {
3583 67105 : VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3584 :
3585 : // If no driver kind is specified, assume all are to be probed.
3586 67105 : if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3587 5857 : nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3588 :
3589 : /* -------------------------------------------------------------------- */
3590 : /* In case of shared dataset, first scan the existing list to see */
3591 : /* if it could already contain the requested dataset. */
3592 : /* -------------------------------------------------------------------- */
3593 67105 : if (nOpenFlags & GDAL_OF_SHARED)
3594 : {
3595 6483 : if (nOpenFlags & GDAL_OF_INTERNAL)
3596 : {
3597 0 : CPLError(CE_Failure, CPLE_IllegalArg,
3598 : "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3599 0 : return nullptr;
3600 : }
3601 :
3602 : auto poSharedDS =
3603 6483 : GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
3604 6483 : if (poSharedDS)
3605 : {
3606 6114 : poSharedDS->Reference();
3607 6114 : return poSharedDS;
3608 : }
3609 : }
3610 :
3611 60991 : GDALDriverManager *poDM = GetGDALDriverManager();
3612 : // CPLLocaleC oLocaleForcer;
3613 :
3614 60991 : CPLErrorReset();
3615 60991 : VSIErrorReset();
3616 60991 : CPLAssert(nullptr != poDM);
3617 :
3618 : // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3619 : // shared dataset was asked before.
3620 : GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3621 121963 : const_cast<char **>(papszSiblingFiles));
3622 60991 : oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3623 :
3624 60991 : GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3625 60991 : if (sAntiRecursion.nRecLevel == 100)
3626 : {
3627 0 : CPLError(CE_Failure, CPLE_AppDefined,
3628 : "GDALOpen() called with too many recursion levels");
3629 0 : return nullptr;
3630 : }
3631 :
3632 121968 : std::string osAllowedDrivers;
3633 149222 : for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
3634 88231 : osAllowedDrivers += pszDriverName;
3635 : auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
3636 182932 : std::string(pszFilename), nOpenFlags, osAllowedDrivers);
3637 60982 : if (sAntiRecursion.aosDatasetNamesWithFlags.find(dsCtxt) !=
3638 121965 : sAntiRecursion.aosDatasetNamesWithFlags.end())
3639 : {
3640 0 : CPLError(CE_Failure, CPLE_AppDefined,
3641 : "GDALOpen() called on %s recursively", pszFilename);
3642 0 : return nullptr;
3643 : }
3644 :
3645 : // Remove leading @ if present.
3646 : char **papszOpenOptionsCleaned =
3647 60984 : CSLDuplicate(const_cast<char **>(papszOpenOptions));
3648 66214 : for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3649 : ++papszIter)
3650 : {
3651 5233 : char *pszOption = *papszIter;
3652 5233 : if (pszOption[0] == '@')
3653 176 : memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3654 : }
3655 :
3656 60981 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3657 60981 : oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
3658 :
3659 : #ifdef OGRAPISPY_ENABLED
3660 60981 : const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3661 : const int iSnapshot =
3662 15895 : (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
3663 76876 : ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
3664 60981 : : INT_MIN;
3665 : #endif
3666 :
3667 60981 : const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
3668 60985 : GDALDriver *poMissingPluginDriver = nullptr;
3669 121975 : std::vector<GDALDriver *> apoSecondPassDrivers;
3670 :
3671 : // Lookup of matching driver for dataset can involve up to 2 passes:
3672 : // - in the first pass, all drivers that are compabile of the request mode
3673 : // (raster/vector/etc.) are probed using their Identify() method if it
3674 : // exists. If the Identify() method returns FALSE, the driver is skipped.
3675 : // If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
3676 : // driver is a deferred-loading plugin, it is added to the
3677 : // apoSecondPassDrivers list for potential later probing, and execution
3678 : // continues to the next driver in the list.
3679 : // Otherwise if Identify() returns non-FALSE, the Open() method is used.
3680 : // If Open() returns a non-NULL dataset, the loop stops and it is
3681 : // returned. Otherwise looping over remaining drivers continues.
3682 : // - the second pass is optional, only if at least one driver was added
3683 : // into apoSecondPassDrivers during the first pass. It is similar
3684 : // to the first pass except it runs only on apoSecondPassDrivers drivers.
3685 : // And the Open() method of such drivers is used, causing them to be
3686 : // loaded for real.
3687 60981 : int iPass = 1;
3688 60993 : retry:
3689 7272830 : for (int iDriver = 0;
3690 7272870 : iDriver < (iPass == 1 ? nDriverCount
3691 39 : : static_cast<int>(apoSecondPassDrivers.size()));
3692 : ++iDriver)
3693 : {
3694 : GDALDriver *poDriver =
3695 7260510 : iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
3696 5314 : : apoSecondPassDrivers[iDriver];
3697 10452900 : if (papszAllowedDrivers != nullptr &&
3698 3189980 : CSLFindString(papszAllowedDrivers,
3699 : GDALGetDriverShortName(poDriver)) == -1)
3700 : {
3701 6750810 : continue;
3702 : }
3703 :
3704 4155990 : if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
3705 36667 : continue;
3706 :
3707 11101600 : if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
3708 6104280 : (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3709 1984840 : poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
3710 492544 : continue;
3711 10489900 : if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3712 5231140 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3713 1604240 : poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
3714 1246430 : continue;
3715 5033590 : if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3716 2520520 : (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3717 140048 : poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
3718 132208 : continue;
3719 :
3720 : // Remove general OVERVIEW_LEVEL open options from list before passing
3721 : // it to the driver, if it isn't a driver specific option already.
3722 2248270 : char **papszTmpOpenOptions = nullptr;
3723 2248270 : char **papszTmpOpenOptionsToValidate = nullptr;
3724 2248270 : char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3725 6738600 : if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3726 2248370 : nullptr &&
3727 105 : (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) == nullptr ||
3728 2246490 : CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
3729 79 : .ifind("OVERVIEW_LEVEL") == std::string::npos))
3730 : {
3731 105 : papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3732 : papszTmpOpenOptions =
3733 105 : CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3734 105 : oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3735 :
3736 105 : papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3737 105 : papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
3738 : "OVERVIEW_LEVEL", nullptr);
3739 105 : papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3740 : }
3741 :
3742 : const int nIdentifyRes =
3743 2243930 : poDriver->pfnIdentifyEx
3744 4488370 : ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
3745 2243920 : : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
3746 2244460 : : GDAL_IDENTIFY_UNKNOWN;
3747 2244460 : if (nIdentifyRes == FALSE)
3748 : {
3749 1736530 : CSLDestroy(papszTmpOpenOptions);
3750 1736020 : CSLDestroy(papszTmpOpenOptionsToValidate);
3751 1735950 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3752 1735950 : continue;
3753 : }
3754 510580 : else if (iPass == 1 && nIdentifyRes < 0 &&
3755 1036440 : poDriver->pfnOpen == nullptr &&
3756 17940 : poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
3757 : {
3758 : // Not loaded plugin
3759 119 : apoSecondPassDrivers.push_back(poDriver);
3760 119 : CSLDestroy(papszTmpOpenOptions);
3761 119 : CSLDestroy(papszTmpOpenOptionsToValidate);
3762 119 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3763 119 : continue;
3764 : }
3765 :
3766 507803 : const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
3767 507803 : if (bIdentifyRes)
3768 : {
3769 42162 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3770 : }
3771 :
3772 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3773 : const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3774 : CPLErrorReset();
3775 : #endif
3776 :
3777 507797 : sAntiRecursion.nRecLevel++;
3778 507797 : sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3779 :
3780 510228 : GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
3781 :
3782 510397 : sAntiRecursion.nRecLevel--;
3783 510397 : sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3784 :
3785 510288 : if (poDriver->pfnOpen != nullptr)
3786 : {
3787 : // If we couldn't determine for sure with Identify() (it returned
3788 : // -1), but Open() managed to open the file, post validate options.
3789 492379 : if (poDS != nullptr &&
3790 42728 : (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
3791 41950 : !bIdentifyRes)
3792 : {
3793 757 : GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3794 : }
3795 : }
3796 17909 : else if (poDriver->pfnOpenWithDriverArg != nullptr)
3797 : {
3798 : // do nothing
3799 : }
3800 0 : else if (bIdentifyRes &&
3801 0 : poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
3802 : {
3803 0 : if (!poMissingPluginDriver)
3804 : {
3805 0 : poMissingPluginDriver = poDriver;
3806 : }
3807 : }
3808 : else
3809 : {
3810 : // should not happen given the GDAL_DCAP_OPEN check
3811 0 : CSLDestroy(papszTmpOpenOptions);
3812 0 : CSLDestroy(papszTmpOpenOptionsToValidate);
3813 0 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3814 0 : continue;
3815 : }
3816 :
3817 510288 : CSLDestroy(papszTmpOpenOptions);
3818 510124 : CSLDestroy(papszTmpOpenOptionsToValidate);
3819 509908 : oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3820 :
3821 509908 : if (poDS != nullptr)
3822 : {
3823 42745 : if (poDS->papszOpenOptions == nullptr)
3824 : {
3825 42494 : poDS->papszOpenOptions = papszOpenOptionsCleaned;
3826 42494 : papszOpenOptionsCleaned = nullptr;
3827 : }
3828 :
3829 : // Deal with generic OVERVIEW_LEVEL open option, unless it is
3830 : // driver specific.
3831 128235 : if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
3832 42772 : nullptr &&
3833 27 : (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) ==
3834 54 : nullptr ||
3835 42772 : CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
3836 27 : .ifind("OVERVIEW_LEVEL") == std::string::npos))
3837 : {
3838 : CPLString osVal(
3839 54 : CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
3840 27 : const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
3841 : const bool bThisLevelOnly =
3842 27 : nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
3843 : GDALDataset *poOvrDS =
3844 27 : GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
3845 27 : if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
3846 : {
3847 4 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3848 : {
3849 0 : CPLError(
3850 : CE_Warning, CPLE_NotSupported,
3851 : "A dataset opened by GDALOpenShared should have "
3852 : "the same filename (%s) "
3853 : "and description (%s)",
3854 0 : pszFilename, poDS->GetDescription());
3855 : }
3856 : else
3857 : {
3858 4 : CSLDestroy(poDS->papszOpenOptions);
3859 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3860 4 : poDS->papszOpenOptions = CSLSetNameValue(
3861 : poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
3862 : }
3863 : }
3864 27 : poDS->ReleaseRef();
3865 27 : poDS = poOvrDS;
3866 27 : if (poDS == nullptr)
3867 : {
3868 1 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
3869 : {
3870 1 : CPLError(CE_Failure, CPLE_OpenFailed,
3871 : "Cannot open overview level %d of %s",
3872 : nOvrLevel, pszFilename);
3873 : }
3874 : }
3875 : else
3876 : {
3877 26 : if (!(nOpenFlags & GDAL_OF_INTERNAL))
3878 : {
3879 26 : poDS->AddToDatasetOpenList();
3880 : }
3881 26 : if (nOpenFlags & GDAL_OF_SHARED)
3882 : {
3883 4 : CSLDestroy(poDS->papszOpenOptions);
3884 4 : poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3885 4 : poDS->nOpenFlags = nOpenFlags;
3886 4 : poDS->MarkAsShared();
3887 : }
3888 : }
3889 : }
3890 42718 : else if (nOpenFlags & GDAL_OF_SHARED)
3891 : {
3892 358 : if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3893 : {
3894 2 : CPLError(CE_Warning, CPLE_NotSupported,
3895 : "A dataset opened by GDALOpenShared should have "
3896 : "the same filename (%s) "
3897 : "and description (%s)",
3898 2 : pszFilename, poDS->GetDescription());
3899 : }
3900 : else
3901 : {
3902 356 : poDS->MarkAsShared();
3903 : }
3904 : }
3905 :
3906 42745 : VSIErrorReset();
3907 :
3908 42745 : CSLDestroy(papszOpenOptionsCleaned);
3909 :
3910 : #ifdef OGRAPISPY_ENABLED
3911 42745 : if (iSnapshot != INT_MIN)
3912 : {
3913 9896 : GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
3914 9896 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3915 9896 : poDS = GDALDataset::FromHandle(hDS);
3916 : }
3917 : #endif
3918 :
3919 43528 : return poDS;
3920 : }
3921 :
3922 : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3923 : if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
3924 : {
3925 : // In case the file descriptor was "consumed" by a driver
3926 : // that ultimately failed, re-open it for next drivers.
3927 : oOpenInfo.fpL = VSIFOpenL(
3928 : pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
3929 : }
3930 : #else
3931 467163 : if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
3932 : {
3933 6095 : CSLDestroy(papszOpenOptionsCleaned);
3934 :
3935 : #ifdef OGRAPISPY_ENABLED
3936 783 : if (iSnapshot != INT_MIN)
3937 : {
3938 138 : GDALDatasetH hDS = nullptr;
3939 138 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3940 : }
3941 : #endif
3942 783 : return nullptr;
3943 : }
3944 : #endif
3945 : }
3946 :
3947 : // cppcheck-suppress knownConditionTrueFalse
3948 12347 : if (iPass == 1 && !apoSecondPassDrivers.empty())
3949 : {
3950 16 : CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
3951 12 : iPass = 2;
3952 12 : goto retry;
3953 : }
3954 :
3955 12325 : CSLDestroy(papszOpenOptionsCleaned);
3956 :
3957 : #ifdef OGRAPISPY_ENABLED
3958 17449 : if (iSnapshot != INT_MIN)
3959 : {
3960 858 : GDALDatasetH hDS = nullptr;
3961 858 : OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3962 : }
3963 : #endif
3964 :
3965 17449 : if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
3966 : {
3967 : // Check to see if there was a filesystem error, and report it if so.
3968 : // If not, return a more generic error.
3969 5646 : if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
3970 : {
3971 147 : if (nDriverCount == 0)
3972 : {
3973 1 : CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
3974 : }
3975 146 : else if (oOpenInfo.bStatOK)
3976 : {
3977 140 : if (!poMissingPluginDriver)
3978 : {
3979 140 : CPLError(CE_Failure, CPLE_OpenFailed,
3980 : "`%s' not recognized as being in a supported file "
3981 : "format.",
3982 : pszFilename);
3983 : }
3984 : else
3985 : {
3986 0 : std::string osMsg("`");
3987 0 : osMsg += pszFilename;
3988 : osMsg +=
3989 : "' not recognized as being in a supported file format. "
3990 0 : "It could have been recognized by driver ";
3991 0 : osMsg += poMissingPluginDriver->GetDescription();
3992 0 : osMsg += ", but plugin ";
3993 : osMsg += poMissingPluginDriver->GetMetadataItem(
3994 0 : "MISSING_PLUGIN_FILENAME");
3995 : osMsg += " is not available in your "
3996 0 : "installation.";
3997 0 : if (const char *pszInstallationMsg =
3998 0 : poMissingPluginDriver->GetMetadataItem(
3999 0 : GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE))
4000 : {
4001 0 : osMsg += " ";
4002 0 : osMsg += pszInstallationMsg;
4003 : }
4004 :
4005 : VSIStatBuf sStat;
4006 0 : if (const char *pszGDALDriverPath =
4007 0 : CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr))
4008 : {
4009 0 : if (VSIStat(pszGDALDriverPath, &sStat) != 0)
4010 : {
4011 0 : if (osMsg.back() != '.')
4012 0 : osMsg += ".";
4013 0 : osMsg += " Directory '";
4014 0 : osMsg += pszGDALDriverPath;
4015 : osMsg +=
4016 0 : "' pointed by GDAL_DRIVER_PATH does not exist.";
4017 : }
4018 : }
4019 : else
4020 : {
4021 0 : if (osMsg.back() != '.')
4022 0 : osMsg += ".";
4023 : #ifdef INSTALL_PLUGIN_FULL_DIR
4024 : if (VSIStat(INSTALL_PLUGIN_FULL_DIR, &sStat) != 0)
4025 : {
4026 : osMsg += " Directory '";
4027 : osMsg += INSTALL_PLUGIN_FULL_DIR;
4028 : osMsg += "' hardcoded in the GDAL library does not "
4029 : "exist and the GDAL_DRIVER_PATH "
4030 : "configuration option is not set.";
4031 : }
4032 : else
4033 : #endif
4034 : {
4035 : osMsg += " The GDAL_DRIVER_PATH configuration "
4036 0 : "option is not set.";
4037 : }
4038 : }
4039 :
4040 0 : CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
4041 : }
4042 : }
4043 : else
4044 : {
4045 : // If Stat failed and no VSI error was set, assume it is because
4046 : // the file did not exist on the filesystem.
4047 6 : CPLError(CE_Failure, CPLE_OpenFailed,
4048 : "`%s' does not exist in the file system, "
4049 : "and is not recognized as a supported dataset name.",
4050 : pszFilename);
4051 : }
4052 : }
4053 : }
4054 :
4055 17462 : return nullptr;
4056 : }
4057 :
4058 : /************************************************************************/
4059 : /* GDALOpenShared() */
4060 : /************************************************************************/
4061 :
4062 : /**
4063 : * \brief Open a raster file as a GDALDataset.
4064 : *
4065 : * This function works the same as GDALOpen(), but allows the sharing of
4066 : * GDALDataset handles for a dataset with other callers to GDALOpenShared().
4067 : *
4068 : * In particular, GDALOpenShared() will first consult its list of currently
4069 : * open and shared GDALDataset's, and if the GetDescription() name for one
4070 : * exactly matches the pszFilename passed to GDALOpenShared() it will be
4071 : * referenced and returned.
4072 : *
4073 : * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
4074 : * pszFilename from two different threads, a different GDALDataset object will
4075 : * be returned as it is not safe to use the same dataset from different threads,
4076 : * unless the user does explicitly use mutexes in its code.
4077 : *
4078 : * For drivers supporting the VSI virtual file API, it is possible to open a
4079 : * file in a .zip archive (see VSIInstallZipFileHandler()), in a
4080 : * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
4081 : * server (see VSIInstallCurlFileHandler())
4082 : *
4083 : * \sa GDALOpen()
4084 : * \sa GDALOpenEx()
4085 : *
4086 : * @param pszFilename the name of the file to access. In the case of
4087 : * exotic drivers this may not refer to a physical file, but instead contain
4088 : * information for the driver on how to access a dataset. It should be in
4089 : * UTF-8 encoding.
4090 : *
4091 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
4092 : * drivers support only read only access.
4093 : *
4094 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
4095 : * this handle can be cast to a GDALDataset *.
4096 : */
4097 :
4098 5211 : GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4099 : GDALAccess eAccess)
4100 : {
4101 5211 : VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4102 5211 : return GDALOpenEx(pszFilename,
4103 : GDAL_OF_RASTER |
4104 : (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4105 : GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4106 5211 : nullptr, nullptr, nullptr);
4107 : }
4108 :
4109 : /************************************************************************/
4110 : /* GDALClose() */
4111 : /************************************************************************/
4112 :
4113 : /**
4114 : * \brief Close GDAL dataset.
4115 : *
4116 : * For non-shared datasets (opened with GDALOpen()) the dataset is closed
4117 : * using the C++ "delete" operator, recovering all dataset related resources.
4118 : * For shared datasets (opened with GDALOpenShared()) the dataset is
4119 : * dereferenced, and closed only if the referenced count has dropped below 1.
4120 : *
4121 : * @param hDS The dataset to close. May be cast from a "GDALDataset *".
4122 : * @return CE_None in case of success (return value since GDAL 3.7). On a
4123 : * shared dataset whose reference count is not dropped below 1, CE_None will
4124 : * be returned.
4125 : */
4126 :
4127 61174 : CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4128 :
4129 : {
4130 61174 : if (!hDS)
4131 409 : return CE_None;
4132 :
4133 : #ifdef OGRAPISPY_ENABLED
4134 60765 : if (bOGRAPISpyEnabled)
4135 11 : OGRAPISpyPreClose(hDS);
4136 : #endif
4137 :
4138 60765 : GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4139 :
4140 60765 : if (poDS->GetShared())
4141 : {
4142 : /* --------------------------------------------------------------------
4143 : */
4144 : /* If this file is in the shared dataset list then dereference */
4145 : /* it, and only delete/remote it if the reference count has */
4146 : /* dropped to zero. */
4147 : /* --------------------------------------------------------------------
4148 : */
4149 297 : if (poDS->Dereference() > 0)
4150 28 : return CE_None;
4151 :
4152 269 : CPLErr eErr = poDS->Close();
4153 269 : delete poDS;
4154 :
4155 : #ifdef OGRAPISPY_ENABLED
4156 269 : if (bOGRAPISpyEnabled)
4157 0 : OGRAPISpyPostClose();
4158 : #endif
4159 :
4160 269 : return eErr;
4161 : }
4162 :
4163 : /* -------------------------------------------------------------------- */
4164 : /* This is not shared dataset, so directly delete it. */
4165 : /* -------------------------------------------------------------------- */
4166 60468 : CPLErr eErr = poDS->Close();
4167 60467 : delete poDS;
4168 :
4169 : #ifdef OGRAPISPY_ENABLED
4170 60468 : if (bOGRAPISpyEnabled)
4171 11 : OGRAPISpyPostClose();
4172 : #endif
4173 60467 : return eErr;
4174 : }
4175 :
4176 : /************************************************************************/
4177 : /* GDALDumpOpenDataset() */
4178 : /************************************************************************/
4179 :
4180 0 : static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
4181 : {
4182 0 : SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
4183 0 : FILE *fp = static_cast<FILE *>(user_data);
4184 0 : GDALDataset *poDS = psStruct->poDS;
4185 :
4186 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4187 0 : ? "DriverIsNULL"
4188 0 : : poDS->GetDriver()->GetDescription();
4189 :
4190 0 : poDS->Reference();
4191 0 : CPL_IGNORE_RET_VAL(
4192 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4193 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName,
4194 0 : static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
4195 : poDS->GetRasterYSize(), poDS->GetRasterCount(),
4196 0 : poDS->GetDescription()));
4197 :
4198 0 : return TRUE;
4199 : }
4200 :
4201 0 : static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
4202 : {
4203 :
4204 : // Don't list shared datasets. They have already been listed by
4205 : // GDALDumpOpenSharedDatasetsForeach.
4206 0 : if (poDS->GetShared())
4207 0 : return TRUE;
4208 :
4209 0 : const char *pszDriverName = poDS->GetDriver() == nullptr
4210 0 : ? "DriverIsNULL"
4211 0 : : poDS->GetDriver()->GetDescription();
4212 :
4213 0 : poDS->Reference();
4214 0 : CPL_IGNORE_RET_VAL(
4215 0 : VSIFPrintf(fp, " %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4216 0 : poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
4217 : poDS->GetRasterXSize(), poDS->GetRasterYSize(),
4218 0 : poDS->GetRasterCount(), poDS->GetDescription()));
4219 :
4220 0 : return TRUE;
4221 : }
4222 :
4223 : /**
4224 : * \brief List open datasets.
4225 : *
4226 : * Dumps a list of all open datasets (shared or not) to the indicated
4227 : * text file (may be stdout or stderr). This function is primarily intended
4228 : * to assist in debugging "dataset leaks" and reference counting issues.
4229 : * The information reported includes the dataset name, referenced count,
4230 : * shared status, driver name, size, and band count.
4231 : */
4232 :
4233 245 : int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
4234 :
4235 : {
4236 245 : VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
4237 :
4238 490 : CPLMutexHolderD(&hDLMutex);
4239 :
4240 245 : if (poAllDatasetMap == nullptr)
4241 245 : return 0;
4242 :
4243 0 : CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
4244 :
4245 0 : for (const auto &oIter : *poAllDatasetMap)
4246 : {
4247 0 : GDALDumpOpenDatasetsForeach(oIter.first, fp);
4248 : }
4249 :
4250 0 : if (phSharedDatasetSet != nullptr)
4251 : {
4252 0 : CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
4253 : fp);
4254 : }
4255 0 : return static_cast<int>(poAllDatasetMap->size());
4256 : }
4257 :
4258 : /************************************************************************/
4259 : /* BeginAsyncReader() */
4260 : /************************************************************************/
4261 :
4262 : /**
4263 : * \brief Sets up an asynchronous data request
4264 : *
4265 : * This method establish an asynchronous raster read request for the
4266 : * indicated window on the dataset into the indicated buffer. The parameters
4267 : * for windowing, buffer size, buffer type and buffer organization are similar
4268 : * to those for GDALDataset::RasterIO(); however, this call only launches
4269 : * the request and filling the buffer is accomplished via calls to
4270 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4271 : *
4272 : * Once all processing for the created session is complete, or if no further
4273 : * refinement of the request is required, the GDALAsyncReader object should
4274 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4275 : *
4276 : * Note that the data buffer (pData) will potentially continue to be
4277 : * updated as long as the session lives, but it is not deallocated when
4278 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4279 : * should be deallocated by the application at that point.
4280 : *
4281 : * Additional information on asynchronous IO in GDAL may be found at:
4282 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4283 : *
4284 : * This method is the same as the C GDALBeginAsyncReader() function.
4285 : *
4286 : * @param nXOff The pixel offset to the top left corner of the region
4287 : * of the band to be accessed. This would be zero to start from the left side.
4288 : *
4289 : * @param nYOff The line offset to the top left corner of the region
4290 : * of the band to be accessed. This would be zero to start from the top.
4291 : *
4292 : * @param nXSize The width of the region of the band to be accessed in pixels.
4293 : *
4294 : * @param nYSize The height of the region of the band to be accessed in lines.
4295 : *
4296 : * @param pBuf The buffer into which the data should be read. This buffer must
4297 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4298 : * It is organized in left to right,top to bottom pixel order. Spacing is
4299 : * controlled by the nPixelSpace, and nLineSpace parameters.
4300 : *
4301 : * @param nBufXSize the width of the buffer image into which the desired region
4302 : * is to be read, or from which it is to be written.
4303 : *
4304 : * @param nBufYSize the height of the buffer image into which the desired
4305 : * region is to be read, or from which it is to be written.
4306 : *
4307 : * @param eBufType the type of the pixel values in the pData data buffer. The
4308 : * pixel values will automatically be translated to/from the GDALRasterBand
4309 : * data type as needed.
4310 : *
4311 : * @param nBandCount the number of bands being read or written.
4312 : *
4313 : * @param panBandMap the list of nBandCount band numbers being read/written.
4314 : * Note band numbers are 1 based. This may be NULL to select the first
4315 : * nBandCount bands.
4316 : *
4317 : * @param nPixelSpace The byte offset from the start of one pixel value in
4318 : * pData to the start of the next pixel value within a scanline. If defaulted
4319 : * (0) the size of the datatype eBufType is used.
4320 : *
4321 : * @param nLineSpace The byte offset from the start of one scanline in
4322 : * pData to the start of the next. If defaulted the size of the datatype
4323 : * eBufType * nBufXSize is used.
4324 : *
4325 : * @param nBandSpace the byte offset from the start of one bands data to the
4326 : * start of the next. If defaulted (zero) the value will be
4327 : * nLineSpace * nBufYSize implying band sequential organization
4328 : * of the data buffer.
4329 : *
4330 : * @param papszOptions Driver specific control options in a string list or NULL.
4331 : * Consult driver documentation for options supported.
4332 : *
4333 : * @return The GDALAsyncReader object representing the request.
4334 : */
4335 :
4336 1 : GDALAsyncReader *GDALDataset::BeginAsyncReader(
4337 : int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
4338 : int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
4339 : int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
4340 : {
4341 : // See gdaldefaultasync.cpp
4342 :
4343 1 : return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
4344 : nBufXSize, nBufYSize, eBufType, nBandCount,
4345 : panBandMap, nPixelSpace, nLineSpace,
4346 1 : nBandSpace, papszOptions);
4347 : }
4348 :
4349 : /************************************************************************/
4350 : /* GDALBeginAsyncReader() */
4351 : /************************************************************************/
4352 :
4353 : /**
4354 : * \brief Sets up an asynchronous data request
4355 : *
4356 : * This method establish an asynchronous raster read request for the
4357 : * indicated window on the dataset into the indicated buffer. The parameters
4358 : * for windowing, buffer size, buffer type and buffer organization are similar
4359 : * to those for GDALDataset::RasterIO(); however, this call only launches
4360 : * the request and filling the buffer is accomplished via calls to
4361 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4362 : *
4363 : * Once all processing for the created session is complete, or if no further
4364 : * refinement of the request is required, the GDALAsyncReader object should
4365 : * be destroyed with the GDALDataset::EndAsyncReader() method.
4366 : *
4367 : * Note that the data buffer (pData) will potentially continue to be
4368 : * updated as long as the session lives, but it is not deallocated when
4369 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
4370 : * should be deallocated by the application at that point.
4371 : *
4372 : * Additional information on asynchronous IO in GDAL may be found at:
4373 : * https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4374 : *
4375 : * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
4376 : *
4377 : * @param hDS handle to the dataset object.
4378 : *
4379 : * @param nXOff The pixel offset to the top left corner of the region
4380 : * of the band to be accessed. This would be zero to start from the left side.
4381 : *
4382 : * @param nYOff The line offset to the top left corner of the region
4383 : * of the band to be accessed. This would be zero to start from the top.
4384 : *
4385 : * @param nXSize The width of the region of the band to be accessed in pixels.
4386 : *
4387 : * @param nYSize The height of the region of the band to be accessed in lines.
4388 : *
4389 : * @param pBuf The buffer into which the data should be read. This buffer must
4390 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4391 : * It is organized in left to right,top to bottom pixel order. Spacing is
4392 : * controlled by the nPixelSpace, and nLineSpace parameters.
4393 : *
4394 : * @param nBufXSize the width of the buffer image into which the desired region
4395 : * is to be read, or from which it is to be written.
4396 : *
4397 : * @param nBufYSize the height of the buffer image into which the desired
4398 : * region is to be read, or from which it is to be written.
4399 : *
4400 : * @param eBufType the type of the pixel values in the pData data buffer. The
4401 : * pixel values will automatically be translated to/from the GDALRasterBand
4402 : * data type as needed.
4403 : *
4404 : * @param nBandCount the number of bands being read or written.
4405 : *
4406 : * @param panBandMap the list of nBandCount band numbers being read/written.
4407 : * Note band numbers are 1 based. This may be NULL to select the first
4408 : * nBandCount bands.
4409 : *
4410 : * @param nPixelSpace The byte offset from the start of one pixel value in
4411 : * pData to the start of the next pixel value within a scanline. If defaulted
4412 : * (0) the size of the datatype eBufType is used.
4413 : *
4414 : * @param nLineSpace The byte offset from the start of one scanline in
4415 : * pData to the start of the next. If defaulted the size of the datatype
4416 : * eBufType * nBufXSize is used.
4417 : *
4418 : * @param nBandSpace the byte offset from the start of one bands data to the
4419 : * start of the next. If defaulted (zero) the value will be
4420 : * nLineSpace * nBufYSize implying band sequential organization
4421 : * of the data buffer.
4422 : *
4423 : * @param papszOptions Driver specific control options in a string list or NULL.
4424 : * Consult driver documentation for options supported.
4425 : *
4426 : * @return handle representing the request.
4427 : */
4428 :
4429 1 : GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
4430 : GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
4431 : int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
4432 : int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
4433 : CSLConstList papszOptions)
4434 :
4435 : {
4436 1 : VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
4437 : return static_cast<GDALAsyncReaderH>(
4438 1 : GDALDataset::FromHandle(hDS)->BeginAsyncReader(
4439 : nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
4440 : nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
4441 1 : const_cast<char **>(papszOptions)));
4442 : }
4443 :
4444 : /************************************************************************/
4445 : /* EndAsyncReader() */
4446 : /************************************************************************/
4447 :
4448 : /**
4449 : * End asynchronous request.
4450 : *
4451 : * This method destroys an asynchronous io request and recovers all
4452 : * resources associated with it.
4453 : *
4454 : * This method is the same as the C function GDALEndAsyncReader().
4455 : *
4456 : * @param poARIO pointer to a GDALAsyncReader
4457 : */
4458 :
4459 1 : void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
4460 : {
4461 1 : delete poARIO;
4462 1 : }
4463 :
4464 : /************************************************************************/
4465 : /* GDALEndAsyncReader() */
4466 : /************************************************************************/
4467 :
4468 : /**
4469 : * End asynchronous request.
4470 : *
4471 : * This method destroys an asynchronous io request and recovers all
4472 : * resources associated with it.
4473 : *
4474 : * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4475 : *
4476 : * @param hDS handle to the dataset object.
4477 : * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4478 : */
4479 :
4480 1 : void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
4481 : GDALAsyncReaderH hAsyncReaderH)
4482 : {
4483 1 : VALIDATE_POINTER0(hDS, "GDALDataset");
4484 1 : VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4485 1 : GDALDataset::FromHandle(hDS)->EndAsyncReader(
4486 1 : static_cast<GDALAsyncReader *>(hAsyncReaderH));
4487 : }
4488 :
4489 : /************************************************************************/
4490 : /* CloseDependentDatasets() */
4491 : /************************************************************************/
4492 :
4493 : /**
4494 : * Drop references to any other datasets referenced by this dataset.
4495 : *
4496 : * This method should release any reference to other datasets (e.g. a VRT
4497 : * dataset to its sources), but not close the current dataset itself.
4498 : *
4499 : * If at least, one reference to a dependent dataset has been dropped,
4500 : * this method should return TRUE. Otherwise it *should* return FALSE.
4501 : * (Failure to return the proper value might result in infinite loop)
4502 : *
4503 : * This method can be called several times on a given dataset. After
4504 : * the first time, it should not do anything and return FALSE.
4505 : *
4506 : * The driver implementation may choose to destroy its raster bands,
4507 : * so be careful not to call any method on the raster bands afterwards.
4508 : *
4509 : * Basically the only safe action you can do after calling
4510 : * CloseDependentDatasets() is to call the destructor.
4511 : *
4512 : * Note: the only legitimate caller of CloseDependentDatasets() is
4513 : * GDALDriverManager::~GDALDriverManager()
4514 : *
4515 : * @return TRUE if at least one reference to another dataset has been dropped.
4516 : */
4517 17769 : int GDALDataset::CloseDependentDatasets()
4518 : {
4519 17769 : return oOvManager.CloseDependentDatasets();
4520 : }
4521 :
4522 : /************************************************************************/
4523 : /* ReportError() */
4524 : /************************************************************************/
4525 :
4526 : #ifndef DOXYGEN_XML
4527 : /**
4528 : * \brief Emits an error related to a dataset.
4529 : *
4530 : * This function is a wrapper for regular CPLError(). The only difference
4531 : * with CPLError() is that it prepends the error message with the dataset
4532 : * name.
4533 : *
4534 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4535 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4536 : * @param fmt a printf() style format string. Any additional arguments
4537 : * will be treated as arguments to fill in this format in a manner
4538 : * similar to printf().
4539 : *
4540 : * @since GDAL 1.9.0
4541 : */
4542 :
4543 74 : void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4544 : const char *fmt, ...) const
4545 : {
4546 : va_list args;
4547 74 : va_start(args, fmt);
4548 74 : ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4549 74 : va_end(args);
4550 74 : }
4551 :
4552 : /**
4553 : * \brief Emits an error related to a dataset (static method)
4554 : *
4555 : * This function is a wrapper for regular CPLError(). The only difference
4556 : * with CPLError() is that it prepends the error message with the dataset
4557 : * name.
4558 : *
4559 : * @param pszDSName dataset name.
4560 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4561 : * @param err_no the error number (CPLE_*) from cpl_error.h.
4562 : * @param fmt a printf() style format string. Any additional arguments
4563 : * will be treated as arguments to fill in this format in a manner
4564 : * similar to printf().
4565 : *
4566 : * @since GDAL 3.2.0
4567 : */
4568 :
4569 91 : void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4570 : CPLErrorNum err_no, const char *fmt, ...)
4571 : {
4572 : va_list args;
4573 91 : va_start(args, fmt);
4574 91 : ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4575 91 : va_end(args);
4576 91 : }
4577 :
4578 165 : void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4579 : CPLErrorNum err_no, const char *fmt,
4580 : va_list args)
4581 : {
4582 165 : pszDSName = CPLGetFilename(pszDSName);
4583 165 : if (pszDSName[0] != '\0')
4584 : {
4585 159 : CPLError(eErrClass, err_no, "%s",
4586 318 : std::string(pszDSName)
4587 159 : .append(": ")
4588 318 : .append(CPLString().vPrintf(fmt, args))
4589 : .c_str());
4590 : }
4591 : else
4592 : {
4593 6 : CPLErrorV(eErrClass, err_no, fmt, args);
4594 : }
4595 165 : }
4596 : #endif
4597 :
4598 : /************************************************************************/
4599 : /* GetMetadata() */
4600 : /************************************************************************/
4601 50983 : char **GDALDataset::GetMetadata(const char *pszDomain)
4602 : {
4603 50983 : if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4604 : {
4605 7 : oDerivedMetadataList.Clear();
4606 :
4607 : // First condition: at least one raster band.
4608 7 : if (GetRasterCount() > 0)
4609 : {
4610 : // Check if there is at least one complex band.
4611 7 : bool hasAComplexBand = false;
4612 :
4613 12 : for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4614 : {
4615 7 : if (GDALDataTypeIsComplex(
4616 7 : GetRasterBand(rasterId)->GetRasterDataType()))
4617 : {
4618 2 : hasAComplexBand = true;
4619 2 : break;
4620 : }
4621 : }
4622 :
4623 7 : unsigned int nbSupportedDerivedDS = 0;
4624 : const DerivedDatasetDescription *poDDSDesc =
4625 7 : GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4626 :
4627 7 : int nNumDataset = 1;
4628 56 : for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4629 : ++derivedId)
4630 : {
4631 84 : if (hasAComplexBand ||
4632 84 : CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4633 : "complex")
4634 : {
4635 : oDerivedMetadataList.SetNameValue(
4636 : CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4637 : CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4638 19 : poDDSDesc[derivedId].pszDatasetName,
4639 19 : GetDescription()));
4640 :
4641 : CPLString osDesc(
4642 : CPLSPrintf("%s from %s",
4643 19 : poDDSDesc[derivedId].pszDatasetDescription,
4644 19 : GetDescription()));
4645 : oDerivedMetadataList.SetNameValue(
4646 : CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4647 19 : osDesc.c_str());
4648 :
4649 19 : nNumDataset++;
4650 : }
4651 : }
4652 : }
4653 7 : return oDerivedMetadataList.List();
4654 : }
4655 :
4656 50976 : return GDALMajorObject::GetMetadata(pszDomain);
4657 : }
4658 :
4659 : /**
4660 : * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4661 : * \brief Set metadata.
4662 : *
4663 : * CAUTION: depending on the format, older values of the updated information
4664 : * might still be found in the file in a "ghost" state, even if no longer
4665 : * accessible through the GDAL API. This is for example the case of the GTiff
4666 : * format (this is not a exhaustive list)
4667 : *
4668 : * The C function GDALSetMetadata() does the same thing as this method.
4669 : *
4670 : * @param papszMetadata the metadata in name=value string list format to
4671 : * apply.
4672 : * @param pszDomain the domain of interest. Use "" or NULL for the default
4673 : * domain.
4674 : * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4675 : * metadata has been accepted, but is likely not maintained persistently
4676 : * by the underlying object between sessions.
4677 : */
4678 :
4679 : /**
4680 : * \fn GDALDataset::SetMetadataItem( const char * pszName, const char *
4681 : * pszValue, const char * pszDomain)
4682 : * \brief Set single metadata item.
4683 : *
4684 : * CAUTION: depending on the format, older values of the updated information
4685 : * might still be found in the file in a "ghost" state, even if no longer
4686 : * accessible through the GDAL API. This is for example the case of the GTiff
4687 : * format (this is not a exhaustive list)
4688 : *
4689 : * The C function GDALSetMetadataItem() does the same thing as this method.
4690 : *
4691 : * @param pszName the key for the metadata item to fetch.
4692 : * @param pszValue the value to assign to the key.
4693 : * @param pszDomain the domain to set within, use NULL for the default domain.
4694 : *
4695 : * @return CE_None on success, or an error code on failure.
4696 : */
4697 :
4698 : /************************************************************************/
4699 : /* GetMetadataDomainList() */
4700 : /************************************************************************/
4701 :
4702 731 : char **GDALDataset::GetMetadataDomainList()
4703 : {
4704 731 : char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4705 :
4706 : // Ensure that we do not duplicate DERIVED domain.
4707 864 : if (GetRasterCount() > 0 &&
4708 133 : CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4709 : {
4710 : currentDomainList =
4711 133 : CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4712 : }
4713 731 : return currentDomainList;
4714 : }
4715 :
4716 : /************************************************************************/
4717 : /* GetDriverName() */
4718 : /************************************************************************/
4719 :
4720 : /** Return driver name.
4721 : * @return driver name.
4722 : */
4723 2017 : const char *GDALDataset::GetDriverName()
4724 : {
4725 2017 : if (poDriver)
4726 2005 : return poDriver->GetDescription();
4727 12 : return "";
4728 : }
4729 :
4730 : /************************************************************************/
4731 : /* GDALDatasetReleaseResultSet() */
4732 : /************************************************************************/
4733 :
4734 : /**
4735 : \brief Release results of ExecuteSQL().
4736 :
4737 : This function should only be used to deallocate OGRLayers resulting from
4738 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
4739 : results set before destroying the GDALDataset may cause errors.
4740 :
4741 : This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4742 :
4743 : @since GDAL 2.0
4744 :
4745 : @param hDS the dataset handle.
4746 : @param hLayer the result of a previous ExecuteSQL() call.
4747 :
4748 : */
4749 2525 : void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
4750 :
4751 : {
4752 2525 : VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4753 :
4754 : #ifdef OGRAPISPY_ENABLED
4755 2525 : if (bOGRAPISpyEnabled)
4756 6 : OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4757 : #endif
4758 :
4759 5050 : GDALDataset::FromHandle(hDS)->ReleaseResultSet(
4760 2525 : OGRLayer::FromHandle(hLayer));
4761 : }
4762 :
4763 : /************************************************************************/
4764 : /* GDALDatasetGetLayerCount() */
4765 : /************************************************************************/
4766 :
4767 : /**
4768 : \brief Get the number of layers in this dataset.
4769 :
4770 : This function is the same as the C++ method GDALDataset::GetLayerCount()
4771 :
4772 : @since GDAL 2.0
4773 :
4774 : @param hDS the dataset handle.
4775 : @return layer count.
4776 : */
4777 :
4778 1278 : int GDALDatasetGetLayerCount(GDALDatasetH hDS)
4779 :
4780 : {
4781 1278 : VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4782 :
4783 : #ifdef OGRAPISPY_ENABLED
4784 1278 : if (bOGRAPISpyEnabled)
4785 2 : OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4786 : #endif
4787 :
4788 1278 : return GDALDataset::FromHandle(hDS)->GetLayerCount();
4789 : }
4790 :
4791 : /************************************************************************/
4792 : /* GDALDatasetGetLayer() */
4793 : /************************************************************************/
4794 :
4795 : /**
4796 : \brief Fetch a layer by index.
4797 :
4798 : The returned layer remains owned by the
4799 : GDALDataset and should not be deleted by the application.
4800 :
4801 : This function is the same as the C++ method GDALDataset::GetLayer()
4802 :
4803 : @since GDAL 2.0
4804 :
4805 : @param hDS the dataset handle.
4806 : @param iLayer a layer number between 0 and GetLayerCount()-1.
4807 :
4808 : @return the layer, or NULL if iLayer is out of range or an error occurs.
4809 : */
4810 :
4811 8207 : OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
4812 :
4813 : {
4814 8207 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
4815 :
4816 : OGRLayerH hLayer =
4817 8207 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
4818 :
4819 : #ifdef OGRAPISPY_ENABLED
4820 8207 : if (bOGRAPISpyEnabled)
4821 3 : OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
4822 : #endif
4823 :
4824 8207 : return hLayer;
4825 : }
4826 :
4827 : /************************************************************************/
4828 : /* GDALDatasetGetLayerByName() */
4829 : /************************************************************************/
4830 :
4831 : /**
4832 : \brief Fetch a layer by name.
4833 :
4834 : The returned layer remains owned by the
4835 : GDALDataset and should not be deleted by the application.
4836 :
4837 : This function is the same as the C++ method GDALDataset::GetLayerByName()
4838 :
4839 : @since GDAL 2.0
4840 :
4841 : @param hDS the dataset handle.
4842 : @param pszName the layer name of the layer to fetch.
4843 :
4844 : @return the layer, or NULL if Layer is not found or an error occurs.
4845 : */
4846 :
4847 2922 : OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
4848 :
4849 : {
4850 2922 : VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
4851 :
4852 2922 : OGRLayerH hLayer = OGRLayer::ToHandle(
4853 2922 : GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
4854 :
4855 : #ifdef OGRAPISPY_ENABLED
4856 2922 : if (bOGRAPISpyEnabled)
4857 4 : OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
4858 : #endif
4859 :
4860 2922 : return hLayer;
4861 : }
4862 :
4863 : /************************************************************************/
4864 : /* GDALDatasetIsLayerPrivate() */
4865 : /************************************************************************/
4866 :
4867 : /**
4868 : \brief Returns true if the layer at the specified index is deemed a private or
4869 : system table, or an internal detail only.
4870 :
4871 : This function is the same as the C++ method GDALDataset::IsLayerPrivate()
4872 :
4873 : @since GDAL 3.4
4874 :
4875 : @param hDS the dataset handle.
4876 : @param iLayer a layer number between 0 and GetLayerCount()-1.
4877 :
4878 : @return true if the layer is a private or system table.
4879 : */
4880 :
4881 91 : int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
4882 :
4883 : {
4884 91 : VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
4885 :
4886 91 : const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
4887 :
4888 91 : return res ? 1 : 0;
4889 : }
4890 :
4891 : /************************************************************************/
4892 : /* GDALDatasetDeleteLayer() */
4893 : /************************************************************************/
4894 :
4895 : /**
4896 : \brief Delete the indicated layer from the datasource.
4897 :
4898 : If this function is supported
4899 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
4900 :
4901 : This method is the same as the C++ method GDALDataset::DeleteLayer().
4902 :
4903 : @since GDAL 2.0
4904 :
4905 : @param hDS the dataset handle.
4906 : @param iLayer the index of the layer to delete.
4907 :
4908 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
4909 : layers is not supported for this datasource.
4910 :
4911 : */
4912 42 : OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
4913 :
4914 : {
4915 42 : VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
4916 :
4917 : #ifdef OGRAPISPY_ENABLED
4918 42 : if (bOGRAPISpyEnabled)
4919 2 : OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
4920 : #endif
4921 :
4922 42 : return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
4923 : }
4924 :
4925 : /************************************************************************/
4926 : /* CreateLayer() */
4927 : /************************************************************************/
4928 :
4929 : /**
4930 : \brief This method attempts to create a new layer on the dataset with the
4931 : indicated name, coordinate system, geometry type.
4932 :
4933 : The papszOptions argument
4934 : can be used to control driver specific creation options. These options are
4935 : normally documented in the format specific documentation.
4936 : That function will try to validate the creation option list passed to the
4937 : driver with the GDALValidateCreationOptions() method. This check can be
4938 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
4939 : to NO.
4940 :
4941 : Drivers should extend the ICreateLayer() method and not
4942 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
4943 : delegating the actual work to ICreateLayer().
4944 :
4945 : This method is the same as the C function GDALDatasetCreateLayer() and the
4946 : deprecated OGR_DS_CreateLayer().
4947 :
4948 : Example:
4949 :
4950 : \code{.cpp}
4951 : #include "gdal.h"
4952 : #include "cpl_string.h"
4953 :
4954 : ...
4955 :
4956 : OGRLayer *poLayer;
4957 : char **papszOptions;
4958 :
4959 : if( !poDS->TestCapability( ODsCCreateLayer ) )
4960 : {
4961 : ...
4962 : }
4963 :
4964 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
4965 : poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
4966 : papszOptions );
4967 : CSLDestroy( papszOptions );
4968 :
4969 : if( poLayer == NULL )
4970 : {
4971 : ...
4972 : }
4973 : \endcode
4974 :
4975 : @param pszName the name for the new layer. This should ideally not
4976 : match any existing layer on the datasource.
4977 : @param poSpatialRef the coordinate system to use for the new layer, or NULL if
4978 : no coordinate system is available.
4979 : @param eGType the geometry type for the layer. Use wkbUnknown if there
4980 : are no constraints on the types geometry to be written.
4981 : @param papszOptions a StringList of name=value options. Options are driver
4982 : specific.
4983 :
4984 : @return NULL is returned on failure, or a new OGRLayer handle on success.
4985 :
4986 : */
4987 :
4988 7118 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
4989 : const OGRSpatialReference *poSpatialRef,
4990 : OGRwkbGeometryType eGType,
4991 : CSLConstList papszOptions)
4992 :
4993 : {
4994 7118 : if (eGType == wkbNone)
4995 : {
4996 437 : return CreateLayer(pszName, nullptr, papszOptions);
4997 : }
4998 : else
4999 : {
5000 13362 : OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5001 6681 : oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5002 6681 : return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5003 : }
5004 : }
5005 :
5006 : /**
5007 : \brief This method attempts to create a new layer on the dataset with the
5008 : indicated name and geometry field definition.
5009 :
5010 : When poGeomFieldDefn is not null, most drivers should honor
5011 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5012 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5013 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5014 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5015 : very few currently.
5016 :
5017 : Note that even if a geometry coordinate precision is set and a driver honors the
5018 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5019 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5020 : with the coordinate precision. That is they are assumed to be valid once their
5021 : coordinates are rounded to it. If it might not be the case, the user may set
5022 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5023 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5024 : the passed geometries.
5025 :
5026 : The papszOptions argument
5027 : can be used to control driver specific creation options. These options are
5028 : normally documented in the format specific documentation.
5029 : This function will try to validate the creation option list passed to the
5030 : driver with the GDALValidateCreationOptions() method. This check can be
5031 : disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5032 : to NO.
5033 :
5034 : Drivers should extend the ICreateLayer() method and not
5035 : CreateLayer(). CreateLayer() adds validation of layer creation options, before
5036 : delegating the actual work to ICreateLayer().
5037 :
5038 : This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5039 :
5040 : @param pszName the name for the new layer. This should ideally not
5041 : match any existing layer on the datasource.
5042 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5043 : or NULL if there is no geometry field.
5044 : @param papszOptions a StringList of name=value options. Options are driver
5045 : specific.
5046 :
5047 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5048 : @since 3.9
5049 :
5050 : */
5051 :
5052 8238 : OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5053 : const OGRGeomFieldDefn *poGeomFieldDefn,
5054 : CSLConstList papszOptions)
5055 :
5056 : {
5057 8238 : if (CPLTestBool(
5058 : CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5059 : {
5060 8238 : ValidateLayerCreationOptions(papszOptions);
5061 : }
5062 :
5063 : OGRLayer *poLayer;
5064 8238 : if (poGeomFieldDefn)
5065 : {
5066 7776 : OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5067 7870 : if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5068 94 : !TestCapability(ODsCCurveGeometries))
5069 : {
5070 23 : oGeomFieldDefn.SetType(
5071 : OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5072 : }
5073 :
5074 7776 : poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5075 : }
5076 : else
5077 : {
5078 462 : poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5079 : }
5080 : #ifdef DEBUG
5081 8309 : if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5082 71 : !poLayer->TestCapability(OLCCurveGeometries))
5083 : {
5084 0 : CPLError(CE_Warning, CPLE_AppDefined,
5085 : "Inconsistent driver: Layer geometry type is non-linear, but "
5086 : "TestCapability(OLCCurveGeometries) returns FALSE.");
5087 : }
5088 : #endif
5089 :
5090 8238 : return poLayer;
5091 : }
5092 :
5093 : //! @cond Doxygen_Suppress
5094 :
5095 : // Technical override to avoid ambiguous choice between the old and new
5096 : // new CreateLayer() signatures.
5097 7 : OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5098 : {
5099 14 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5100 14 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5101 : }
5102 :
5103 : // Technical override to avoid ambiguous choice between the old and new
5104 : // new CreateLayer() signatures.
5105 1 : OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5106 : {
5107 2 : OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5108 2 : return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5109 : }
5110 :
5111 : //!@endcond
5112 :
5113 : /************************************************************************/
5114 : /* GDALDatasetCreateLayer() */
5115 : /************************************************************************/
5116 :
5117 : /**
5118 : \brief This function attempts to create a new layer on the dataset with the
5119 : indicated name, coordinate system, geometry type.
5120 :
5121 : The papszOptions argument can be used to control driver specific creation
5122 : options. These options are normally documented in the format specific
5123 : documentation.
5124 :
5125 : This method is the same as the C++ method GDALDataset::CreateLayer().
5126 :
5127 : Example:
5128 :
5129 : \code{.c}
5130 : #include "gdal.h"
5131 : #include "cpl_string.h"
5132 :
5133 : ...
5134 :
5135 : OGRLayerH hLayer;
5136 : char **papszOptions;
5137 :
5138 : if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5139 : {
5140 : ...
5141 : }
5142 :
5143 : papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5144 : hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5145 : papszOptions );
5146 : CSLDestroy( papszOptions );
5147 :
5148 : if( hLayer == NULL )
5149 : {
5150 : ...
5151 : }
5152 : \endcode
5153 :
5154 : @since GDAL 2.0
5155 :
5156 : @param hDS the dataset handle
5157 : @param pszName the name for the new layer. This should ideally not
5158 : match any existing layer on the datasource.
5159 : @param hSpatialRef the coordinate system to use for the new layer, or NULL if
5160 : no coordinate system is available.
5161 : @param eGType the geometry type for the layer. Use wkbUnknown if there
5162 : are no constraints on the types geometry to be written.
5163 : @param papszOptions a StringList of name=value options. Options are driver
5164 : specific.
5165 :
5166 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5167 :
5168 : */
5169 :
5170 5325 : OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5171 : OGRSpatialReferenceH hSpatialRef,
5172 : OGRwkbGeometryType eGType,
5173 : CSLConstList papszOptions)
5174 :
5175 : {
5176 5325 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5177 :
5178 5325 : if (pszName == nullptr)
5179 : {
5180 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5181 : "Name was NULL in GDALDatasetCreateLayer");
5182 0 : return nullptr;
5183 : }
5184 :
5185 : OGRLayerH hLayer =
5186 10650 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5187 5325 : pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5188 : const_cast<char **>(papszOptions)));
5189 :
5190 : #ifdef OGRAPISPY_ENABLED
5191 5325 : if (bOGRAPISpyEnabled)
5192 8 : OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5193 : const_cast<char **>(papszOptions), hLayer);
5194 : #endif
5195 :
5196 5325 : return hLayer;
5197 : }
5198 :
5199 : /************************************************************************/
5200 : /* GDALDatasetCreateLayerFromGeomFieldDefn() */
5201 : /************************************************************************/
5202 :
5203 : /**
5204 : \brief This function attempts to create a new layer on the dataset with the
5205 : indicated name and geometry field.
5206 :
5207 : When poGeomFieldDefn is not null, most drivers should honor
5208 : poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5209 : Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5210 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5211 : poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5212 : very few currently.
5213 :
5214 : Note that even if a geometry coordinate precision is set and a driver honors the
5215 : GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5216 : OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5217 : with the coordinate precision. That is they are assumed to be valid once their
5218 : coordinates are rounded to it. If it might not be the case, the user may set
5219 : the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5220 : or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5221 : the passed geometries.
5222 :
5223 : The papszOptions argument can be used to control driver specific creation
5224 : options. These options are normally documented in the format specific
5225 : documentation.
5226 :
5227 : This method is the same as the C++ method GDALDataset::CreateLayer().
5228 :
5229 : @param hDS the dataset handle
5230 : @param pszName the name for the new layer. This should ideally not
5231 : match any existing layer on the datasource.
5232 : @param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5233 : a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5234 : for drivers supporting that interface).
5235 : @param papszOptions a StringList of name=value options. Options are driver
5236 : specific.
5237 :
5238 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5239 :
5240 : @since GDAL 3.9
5241 :
5242 : */
5243 :
5244 : OGRLayerH
5245 15 : GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5246 : OGRGeomFieldDefnH hGeomFieldDefn,
5247 : CSLConstList papszOptions)
5248 :
5249 : {
5250 15 : VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5251 :
5252 15 : if (!pszName)
5253 : {
5254 0 : CPLError(CE_Failure, CPLE_ObjectNull,
5255 : "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5256 0 : return nullptr;
5257 : }
5258 :
5259 : OGRLayerH hLayer =
5260 30 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5261 15 : pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5262 : papszOptions));
5263 15 : return hLayer;
5264 : }
5265 :
5266 : /************************************************************************/
5267 : /* GDALDatasetCopyLayer() */
5268 : /************************************************************************/
5269 :
5270 : /**
5271 : \brief Duplicate an existing layer.
5272 :
5273 : This function creates a new layer, duplicate the field definitions of the
5274 : source layer and then duplicate each features of the source layer.
5275 : The papszOptions argument
5276 : can be used to control driver specific creation options. These options are
5277 : normally documented in the format specific documentation.
5278 : The source layer may come from another dataset.
5279 :
5280 : This method is the same as the C++ method GDALDataset::CopyLayer()
5281 :
5282 : @since GDAL 2.0
5283 :
5284 : @param hDS the dataset handle.
5285 : @param hSrcLayer source layer.
5286 : @param pszNewName the name of the layer to create.
5287 : @param papszOptions a StringList of name=value options. Options are driver
5288 : specific.
5289 :
5290 : @return a handle to the layer, or NULL if an error occurs.
5291 : */
5292 10 : OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5293 : const char *pszNewName,
5294 : CSLConstList papszOptions)
5295 :
5296 : {
5297 10 : VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5298 10 : VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5299 10 : VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5300 :
5301 20 : return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5302 : OGRLayer::FromHandle(hSrcLayer), pszNewName,
5303 20 : const_cast<char **>(papszOptions)));
5304 : }
5305 :
5306 : /************************************************************************/
5307 : /* GDALDatasetExecuteSQL() */
5308 : /************************************************************************/
5309 :
5310 : /**
5311 : \brief Execute an SQL statement against the data store.
5312 :
5313 : The result of an SQL query is either NULL for statements that are in error,
5314 : or that have no results set, or an OGRLayer pointer representing a results
5315 : set from the query. Note that this OGRLayer is in addition to the layers
5316 : in the data store and must be destroyed with
5317 : ReleaseResultSet() before the dataset is closed
5318 : (destroyed).
5319 :
5320 : This method is the same as the C++ method GDALDataset::ExecuteSQL()
5321 :
5322 : For more information on the SQL dialect supported internally by OGR
5323 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5324 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5325 : to the underlying RDBMS.
5326 :
5327 : Starting with OGR 1.10, the <a
5328 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5329 : also be used.
5330 :
5331 : @since GDAL 2.0
5332 :
5333 : @param hDS the dataset handle.
5334 : @param pszStatement the SQL statement to execute.
5335 : @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5336 :
5337 : @param pszDialect allows control of the statement dialect. If set to NULL, the
5338 : OGR SQL engine will be used, except for RDBMS drivers that will use their
5339 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
5340 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5341 :
5342 : @return an OGRLayer containing the results of the query. Deallocate with
5343 : GDALDatasetReleaseResultSet().
5344 :
5345 : */
5346 :
5347 9010 : OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5348 : OGRGeometryH hSpatialFilter,
5349 : const char *pszDialect)
5350 :
5351 : {
5352 9010 : VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5353 :
5354 : OGRLayerH hLayer =
5355 18020 : OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5356 9010 : pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5357 :
5358 : #ifdef OGRAPISPY_ENABLED
5359 9010 : if (bOGRAPISpyEnabled)
5360 4 : OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5361 : hLayer);
5362 : #endif
5363 :
5364 9010 : return hLayer;
5365 : }
5366 :
5367 : /************************************************************************/
5368 : /* GDALDatasetAbortSQL() */
5369 : /************************************************************************/
5370 :
5371 : /**
5372 : \brief Abort any SQL statement running in the data store.
5373 :
5374 : This function can be safely called from any thread (pending that the dataset
5375 : object is still alive). Driver implementations will make sure that it can be
5376 : called in a thread-safe way.
5377 :
5378 : This might not be implemented by all drivers. At time of writing, only SQLite,
5379 : GPKG and PG drivers implement it
5380 :
5381 : This method is the same as the C++ method GDALDataset::AbortSQL()
5382 :
5383 : @since GDAL 3.2.0
5384 :
5385 : @param hDS the dataset handle.
5386 :
5387 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5388 : is not supported for this datasource. .
5389 :
5390 : */
5391 :
5392 6 : OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5393 :
5394 : {
5395 6 : VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5396 6 : return GDALDataset::FromHandle(hDS)->AbortSQL();
5397 : }
5398 :
5399 : /************************************************************************/
5400 : /* GDALDatasetGetStyleTable() */
5401 : /************************************************************************/
5402 :
5403 : /**
5404 : \brief Returns dataset style table.
5405 :
5406 : This function is the same as the C++ method GDALDataset::GetStyleTable()
5407 :
5408 : @since GDAL 2.0
5409 :
5410 : @param hDS the dataset handle
5411 : @return handle to a style table which should not be modified or freed by the
5412 : caller.
5413 : */
5414 :
5415 6 : OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5416 :
5417 : {
5418 6 : VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5419 :
5420 : return reinterpret_cast<OGRStyleTableH>(
5421 6 : GDALDataset::FromHandle(hDS)->GetStyleTable());
5422 : }
5423 :
5424 : /************************************************************************/
5425 : /* GDALDatasetSetStyleTableDirectly() */
5426 : /************************************************************************/
5427 :
5428 : /**
5429 : \brief Set dataset style table.
5430 :
5431 : This function operate exactly as GDALDatasetSetStyleTable() except that it
5432 : assumes ownership of the passed table.
5433 :
5434 : This function is the same as the C++ method
5435 : GDALDataset::SetStyleTableDirectly()
5436 :
5437 : @since GDAL 2.0
5438 :
5439 : @param hDS the dataset handle
5440 : @param hStyleTable style table handle to set
5441 :
5442 : */
5443 :
5444 0 : void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5445 : OGRStyleTableH hStyleTable)
5446 :
5447 : {
5448 0 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5449 :
5450 0 : GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5451 0 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5452 : }
5453 :
5454 : /************************************************************************/
5455 : /* GDALDatasetSetStyleTable() */
5456 : /************************************************************************/
5457 :
5458 : /**
5459 : \brief Set dataset style table.
5460 :
5461 : This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5462 : it assumes ownership of the passed table.
5463 :
5464 : This function is the same as the C++ method GDALDataset::SetStyleTable()
5465 :
5466 : @since GDAL 2.0
5467 :
5468 : @param hDS the dataset handle
5469 : @param hStyleTable style table handle to set
5470 :
5471 : */
5472 :
5473 4 : void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5474 :
5475 : {
5476 4 : VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5477 4 : VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5478 :
5479 4 : GDALDataset::FromHandle(hDS)->SetStyleTable(
5480 4 : reinterpret_cast<OGRStyleTable *>(hStyleTable));
5481 : }
5482 :
5483 : /************************************************************************/
5484 : /* ValidateLayerCreationOptions() */
5485 : /************************************************************************/
5486 :
5487 : //! @cond Doxygen_Suppress
5488 8238 : int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5489 : {
5490 : const char *pszOptionList =
5491 8238 : GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5492 8238 : if (pszOptionList == nullptr && poDriver != nullptr)
5493 : {
5494 : pszOptionList =
5495 8189 : poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5496 : }
5497 16476 : CPLString osDataset;
5498 8238 : osDataset.Printf("dataset %s", GetDescription());
5499 8238 : return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5500 16476 : osDataset);
5501 : }
5502 :
5503 : //! @endcond
5504 :
5505 : /************************************************************************/
5506 : /* Release() */
5507 : /************************************************************************/
5508 :
5509 : /**
5510 : \brief Drop a reference to this dataset, and if the reference count drops to one
5511 : close (destroy) the dataset.
5512 :
5513 : This method is the same as the C function OGRReleaseDataSource().
5514 :
5515 : @deprecated. In GDAL 2, use GDALClose() instead
5516 :
5517 : @return OGRERR_NONE on success or an error code.
5518 : */
5519 :
5520 1075 : OGRErr GDALDataset::Release()
5521 :
5522 : {
5523 1075 : ReleaseRef();
5524 1075 : return OGRERR_NONE;
5525 : }
5526 :
5527 : /************************************************************************/
5528 : /* GetRefCount() */
5529 : /************************************************************************/
5530 :
5531 : /**
5532 : \brief Fetch reference count.
5533 :
5534 : This method is the same as the C function OGR_DS_GetRefCount().
5535 :
5536 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5537 :
5538 : @return the current reference count for the datasource object itself.
5539 : */
5540 :
5541 794 : int GDALDataset::GetRefCount() const
5542 : {
5543 794 : return nRefCount;
5544 : }
5545 :
5546 : /************************************************************************/
5547 : /* GetSummaryRefCount() */
5548 : /************************************************************************/
5549 :
5550 : /**
5551 : \brief Fetch reference count of datasource and all owned layers.
5552 :
5553 : This method is the same as the C function OGR_DS_GetSummaryRefCount().
5554 :
5555 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5556 :
5557 : @deprecated
5558 :
5559 : @return the current summary reference count for the datasource and its layers.
5560 : */
5561 :
5562 0 : int GDALDataset::GetSummaryRefCount() const
5563 :
5564 : {
5565 0 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5566 0 : int nSummaryCount = nRefCount;
5567 0 : GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5568 :
5569 0 : for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5570 0 : nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5571 :
5572 0 : return nSummaryCount;
5573 : }
5574 :
5575 : /************************************************************************/
5576 : /* ICreateLayer() */
5577 : /************************************************************************/
5578 :
5579 : /**
5580 : \brief This method attempts to create a new layer on the dataset with the
5581 : indicated name, coordinate system, geometry type.
5582 :
5583 : This method is reserved to implementation by drivers.
5584 :
5585 : The papszOptions argument can be used to control driver specific creation
5586 : options. These options are normally documented in the format specific
5587 : documentation.
5588 :
5589 : @param pszName the name for the new layer. This should ideally not
5590 : match any existing layer on the datasource.
5591 : @param poGeomFieldDefn the geometry field definition to use for the new layer,
5592 : or NULL if there is no geometry field.
5593 : @param papszOptions a StringList of name=value options. Options are driver
5594 : specific.
5595 :
5596 : @return NULL is returned on failure, or a new OGRLayer handle on success.
5597 :
5598 : @since GDAL 2.0 (prototype modified in 3.9)
5599 : */
5600 :
5601 : OGRLayer *
5602 16 : GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5603 : CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5604 : CPL_UNUSED CSLConstList papszOptions)
5605 :
5606 : {
5607 16 : CPLError(CE_Failure, CPLE_NotSupported,
5608 : "CreateLayer() not supported by this dataset.");
5609 :
5610 16 : return nullptr;
5611 : }
5612 :
5613 : /************************************************************************/
5614 : /* CopyLayer() */
5615 : /************************************************************************/
5616 :
5617 : /**
5618 : \brief Duplicate an existing layer.
5619 :
5620 : This method creates a new layer, duplicate the field definitions of the
5621 : source layer and then duplicate each features of the source layer.
5622 : The papszOptions argument
5623 : can be used to control driver specific creation options. These options are
5624 : normally documented in the format specific documentation.
5625 : The source layer may come from another dataset.
5626 :
5627 : This method is the same as the C function GDALDatasetCopyLayer() and the
5628 : deprecated OGR_DS_CopyLayer().
5629 :
5630 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5631 :
5632 : @param poSrcLayer source layer.
5633 : @param pszNewName the name of the layer to create.
5634 : @param papszOptions a StringList of name=value options. Options are driver
5635 : specific. There is a common option to set output layer
5636 : spatial reference: DST_SRSWKT. The option should be in
5637 : WKT format. Starting with GDAL 3.7, the common option
5638 : COPY_MD can be set to NO to prevent the default copying
5639 : of the metadata from the source layer to the target layer.
5640 :
5641 : @return a handle to the layer, or NULL if an error occurs.
5642 : */
5643 :
5644 119 : OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
5645 : char **papszOptions)
5646 :
5647 : {
5648 : /* -------------------------------------------------------------------- */
5649 : /* Create the layer. */
5650 : /* -------------------------------------------------------------------- */
5651 119 : if (!TestCapability(ODsCCreateLayer))
5652 : {
5653 0 : CPLError(CE_Failure, CPLE_NotSupported,
5654 : "This datasource does not support creation of layers.");
5655 0 : return nullptr;
5656 : }
5657 :
5658 119 : const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5659 238 : OGRSpatialReference oDstSpaRef(pszSRSWKT);
5660 119 : oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5661 119 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5662 119 : OGRLayer *poDstLayer = nullptr;
5663 :
5664 238 : CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
5665 119 : aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
5666 119 : aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
5667 :
5668 119 : CPLErrorReset();
5669 119 : const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5670 119 : if (nSrcGeomFieldCount == 1)
5671 : {
5672 73 : OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
5673 73 : if (pszSRSWKT)
5674 5 : oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
5675 73 : poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
5676 73 : aosCleanedUpOptions.List());
5677 : }
5678 : else
5679 : {
5680 : poDstLayer =
5681 46 : ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
5682 : }
5683 :
5684 119 : if (poDstLayer == nullptr)
5685 0 : return nullptr;
5686 :
5687 119 : if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
5688 : {
5689 118 : char **papszMD = poSrcLayer->GetMetadata();
5690 118 : if (papszMD)
5691 5 : poDstLayer->SetMetadata(papszMD);
5692 : }
5693 :
5694 : /* -------------------------------------------------------------------- */
5695 : /* Add fields. Default to copy all fields, and make sure to */
5696 : /* establish a mapping between indices, rather than names, in */
5697 : /* case the target datasource has altered it (e.g. Shapefile */
5698 : /* limited to 10 char field names). */
5699 : /* -------------------------------------------------------------------- */
5700 119 : const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5701 :
5702 : // Initialize the index-to-index map to -1's.
5703 238 : std::vector<int> anMap(nSrcFieldCount, -1);
5704 :
5705 : // Caution: At the time of writing, the MapInfo driver
5706 : // returns NULL until a field has been added.
5707 119 : OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5708 119 : int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5709 252 : for (int iField = 0; iField < nSrcFieldCount; ++iField)
5710 : {
5711 133 : OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5712 266 : OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5713 :
5714 : // The field may have been already created at layer creation.
5715 133 : int iDstField = -1;
5716 133 : if (poDstFDefn)
5717 133 : iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5718 133 : if (iDstField >= 0)
5719 : {
5720 0 : anMap[iField] = iDstField;
5721 : }
5722 133 : else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
5723 : {
5724 : // Now that we've created a field, GetLayerDefn() won't return NULL.
5725 133 : if (poDstFDefn == nullptr)
5726 0 : poDstFDefn = poDstLayer->GetLayerDefn();
5727 :
5728 : // Sanity check: if it fails, the driver is buggy.
5729 266 : if (poDstFDefn != nullptr &&
5730 133 : poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5731 : {
5732 0 : CPLError(CE_Warning, CPLE_AppDefined,
5733 : "The output driver has claimed to have added the %s "
5734 : "field, but it did not!",
5735 : oFieldDefn.GetNameRef());
5736 : }
5737 : else
5738 : {
5739 133 : anMap[iField] = nDstFieldCount;
5740 133 : ++nDstFieldCount;
5741 : }
5742 : }
5743 : }
5744 :
5745 : /* -------------------------------------------------------------------- */
5746 119 : std::unique_ptr<OGRCoordinateTransformation> poCT;
5747 119 : OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5748 119 : if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
5749 0 : sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5750 : {
5751 0 : poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
5752 0 : if (nullptr == poCT)
5753 : {
5754 0 : CPLError(CE_Failure, CPLE_NotSupported,
5755 : "This input/output spatial reference is not supported.");
5756 0 : return nullptr;
5757 : }
5758 : }
5759 : /* -------------------------------------------------------------------- */
5760 : /* Create geometry fields. */
5761 : /* -------------------------------------------------------------------- */
5762 120 : if (nSrcGeomFieldCount > 1 &&
5763 1 : TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
5764 : {
5765 :
5766 3 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5767 : {
5768 2 : if (nullptr == pszSRSWKT)
5769 : {
5770 2 : poDstLayer->CreateGeomField(
5771 2 : poSrcDefn->GetGeomFieldDefn(iField));
5772 : }
5773 : else
5774 : {
5775 : OGRGeomFieldDefn *pDstGeomFieldDefn =
5776 0 : poSrcDefn->GetGeomFieldDefn(iField);
5777 0 : pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
5778 0 : poDstLayer->CreateGeomField(pDstGeomFieldDefn);
5779 : }
5780 : }
5781 : }
5782 :
5783 : /* -------------------------------------------------------------------- */
5784 : /* Check if the destination layer supports transactions and set a */
5785 : /* default number of features in a single transaction. */
5786 : /* -------------------------------------------------------------------- */
5787 : const int nGroupTransactions =
5788 119 : poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
5789 :
5790 : /* -------------------------------------------------------------------- */
5791 : /* Transfer features. */
5792 : /* -------------------------------------------------------------------- */
5793 119 : poSrcLayer->ResetReading();
5794 :
5795 119 : if (nGroupTransactions <= 0)
5796 : {
5797 : while (true)
5798 : {
5799 : auto poFeature =
5800 389 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5801 :
5802 389 : if (poFeature == nullptr)
5803 117 : break;
5804 :
5805 272 : CPLErrorReset();
5806 : auto poDstFeature =
5807 272 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5808 :
5809 272 : if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
5810 : OGRERR_NONE)
5811 : {
5812 0 : CPLError(CE_Failure, CPLE_AppDefined,
5813 : "Unable to translate feature " CPL_FRMT_GIB
5814 : " from layer %s.",
5815 0 : poFeature->GetFID(), poSrcDefn->GetName());
5816 0 : return poDstLayer;
5817 : }
5818 :
5819 272 : if (nullptr != poCT)
5820 : {
5821 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5822 : {
5823 0 : OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
5824 0 : if (nullptr == pGeom)
5825 0 : continue;
5826 :
5827 0 : const OGRErr eErr = pGeom->transform(poCT.get());
5828 0 : if (eErr == OGRERR_NONE)
5829 0 : continue;
5830 :
5831 0 : CPLError(CE_Failure, CPLE_AppDefined,
5832 : "Unable to transform geometry " CPL_FRMT_GIB
5833 : " from layer %s.",
5834 0 : poFeature->GetFID(), poSrcDefn->GetName());
5835 0 : return poDstLayer;
5836 : }
5837 : }
5838 :
5839 272 : poDstFeature->SetFID(poFeature->GetFID());
5840 :
5841 272 : CPLErrorReset();
5842 272 : if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
5843 : {
5844 0 : return poDstLayer;
5845 : }
5846 272 : }
5847 : }
5848 : else
5849 : {
5850 2 : std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
5851 : try
5852 : {
5853 2 : apoDstFeatures.resize(nGroupTransactions);
5854 : }
5855 0 : catch (const std::exception &e)
5856 : {
5857 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
5858 0 : return poDstLayer;
5859 : }
5860 2 : bool bStopTransfer = false;
5861 4 : while (!bStopTransfer)
5862 : {
5863 : /* --------------------------------------------------------------------
5864 : */
5865 : /* Fill the array with features. */
5866 : /* --------------------------------------------------------------------
5867 : */
5868 : // Number of features in the temporary array.
5869 2 : int nFeatCount = 0; // Used after for.
5870 22 : for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
5871 : {
5872 : auto poFeature =
5873 22 : std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5874 :
5875 22 : if (poFeature == nullptr)
5876 : {
5877 2 : bStopTransfer = true;
5878 2 : break;
5879 : }
5880 :
5881 20 : CPLErrorReset();
5882 20 : apoDstFeatures[nFeatCount] =
5883 40 : std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5884 :
5885 40 : if (apoDstFeatures[nFeatCount]->SetFrom(
5886 40 : poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
5887 : {
5888 0 : CPLError(CE_Failure, CPLE_AppDefined,
5889 : "Unable to translate feature " CPL_FRMT_GIB
5890 : " from layer %s.",
5891 0 : poFeature->GetFID(), poSrcDefn->GetName());
5892 0 : bStopTransfer = true;
5893 0 : poFeature.reset();
5894 0 : break;
5895 : }
5896 :
5897 20 : if (nullptr != poCT)
5898 : {
5899 0 : for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5900 : {
5901 : OGRGeometry *pGeom =
5902 0 : apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
5903 0 : if (nullptr == pGeom)
5904 0 : continue;
5905 :
5906 0 : const OGRErr eErr = pGeom->transform(poCT.get());
5907 0 : if (eErr == OGRERR_NONE)
5908 0 : continue;
5909 :
5910 0 : CPLError(CE_Failure, CPLE_AppDefined,
5911 : "Unable to transform geometry " CPL_FRMT_GIB
5912 : " from layer %s.",
5913 0 : poFeature->GetFID(), poSrcDefn->GetName());
5914 0 : bStopTransfer = true;
5915 0 : poFeature.reset();
5916 0 : break;
5917 : }
5918 : }
5919 :
5920 20 : if (poFeature)
5921 : {
5922 20 : apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
5923 : }
5924 : }
5925 :
5926 2 : CPLErrorReset();
5927 2 : bool bStopTransaction = false;
5928 4 : while (!bStopTransaction)
5929 : {
5930 2 : bStopTransaction = true;
5931 2 : if (poDstLayer->StartTransaction() != OGRERR_NONE)
5932 0 : break;
5933 22 : for (int i = 0; i < nFeatCount; ++i)
5934 : {
5935 20 : if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
5936 : OGRERR_NONE)
5937 : {
5938 0 : bStopTransfer = true;
5939 0 : bStopTransaction = false;
5940 0 : break;
5941 : }
5942 20 : apoDstFeatures[i].reset();
5943 : }
5944 2 : if (bStopTransaction)
5945 : {
5946 2 : if (poDstLayer->CommitTransaction() != OGRERR_NONE)
5947 0 : break;
5948 : }
5949 : else
5950 : {
5951 0 : poDstLayer->RollbackTransaction();
5952 : }
5953 : }
5954 : }
5955 : }
5956 :
5957 119 : return poDstLayer;
5958 : }
5959 :
5960 : /************************************************************************/
5961 : /* DeleteLayer() */
5962 : /************************************************************************/
5963 :
5964 : /**
5965 : \fn GDALDataset::DeleteLayer(int)
5966 : \brief Delete the indicated layer from the datasource.
5967 :
5968 : If this method is supported
5969 : the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
5970 :
5971 : This method is the same as the C function GDALDatasetDeleteLayer() and the
5972 : deprecated OGR_DS_DeleteLayer().
5973 :
5974 : In GDAL 1.X, this method used to be in the OGRDataSource class.
5975 :
5976 : @param iLayer the index of the layer to delete.
5977 :
5978 : @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
5979 : layers is not supported for this datasource.
5980 :
5981 : */
5982 :
5983 405 : OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
5984 :
5985 : {
5986 405 : CPLError(CE_Failure, CPLE_NotSupported,
5987 : "DeleteLayer() not supported by this dataset.");
5988 :
5989 405 : return OGRERR_UNSUPPORTED_OPERATION;
5990 : }
5991 :
5992 : /************************************************************************/
5993 : /* GetLayerByName() */
5994 : /************************************************************************/
5995 :
5996 : /**
5997 : \brief Fetch a layer by name.
5998 :
5999 : The returned layer remains owned by the
6000 : GDALDataset and should not be deleted by the application.
6001 :
6002 : This method is the same as the C function GDALDatasetGetLayerByName() and the
6003 : deprecated OGR_DS_GetLayerByName().
6004 :
6005 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6006 :
6007 : @param pszName the layer name of the layer to fetch.
6008 :
6009 : @return the layer, or NULL if Layer is not found or an error occurs.
6010 : */
6011 :
6012 27836 : OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6013 :
6014 : {
6015 55672 : CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6016 :
6017 27836 : if (!pszName)
6018 0 : return nullptr;
6019 :
6020 : // First a case sensitive check.
6021 913296 : for (int i = 0; i < GetLayerCount(); ++i)
6022 : {
6023 895770 : OGRLayer *poLayer = GetLayer(i);
6024 :
6025 895770 : if (strcmp(pszName, poLayer->GetName()) == 0)
6026 10310 : return poLayer;
6027 : }
6028 :
6029 : // Then case insensitive.
6030 877571 : for (int i = 0; i < GetLayerCount(); ++i)
6031 : {
6032 860194 : OGRLayer *poLayer = GetLayer(i);
6033 :
6034 860194 : if (EQUAL(pszName, poLayer->GetName()))
6035 149 : return poLayer;
6036 : }
6037 :
6038 17377 : return nullptr;
6039 : }
6040 :
6041 : //! @cond Doxygen_Suppress
6042 : /************************************************************************/
6043 : /* ProcessSQLCreateIndex() */
6044 : /* */
6045 : /* The correct syntax for creating an index in our dialect of */
6046 : /* SQL is: */
6047 : /* */
6048 : /* CREATE INDEX ON <layername> USING <columnname> */
6049 : /************************************************************************/
6050 :
6051 28 : OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6052 :
6053 : {
6054 28 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6055 :
6056 : /* -------------------------------------------------------------------- */
6057 : /* Do some general syntax checking. */
6058 : /* -------------------------------------------------------------------- */
6059 56 : if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6060 84 : !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6061 28 : !EQUAL(papszTokens[4], "USING"))
6062 : {
6063 0 : CSLDestroy(papszTokens);
6064 0 : CPLError(CE_Failure, CPLE_AppDefined,
6065 : "Syntax error in CREATE INDEX command.\n"
6066 : "Was '%s'\n"
6067 : "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6068 : pszSQLCommand);
6069 0 : return OGRERR_FAILURE;
6070 : }
6071 :
6072 : /* -------------------------------------------------------------------- */
6073 : /* Find the named layer. */
6074 : /* -------------------------------------------------------------------- */
6075 28 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6076 28 : if (poLayer == nullptr)
6077 : {
6078 0 : CPLError(CE_Failure, CPLE_AppDefined,
6079 : "CREATE INDEX ON failed, no such layer as `%s'.",
6080 0 : papszTokens[3]);
6081 0 : CSLDestroy(papszTokens);
6082 0 : return OGRERR_FAILURE;
6083 : }
6084 :
6085 : /* -------------------------------------------------------------------- */
6086 : /* Does this layer even support attribute indexes? */
6087 : /* -------------------------------------------------------------------- */
6088 28 : if (poLayer->GetIndex() == nullptr)
6089 : {
6090 0 : CPLError(CE_Failure, CPLE_AppDefined,
6091 : "CREATE INDEX ON not supported by this driver.");
6092 0 : CSLDestroy(papszTokens);
6093 0 : return OGRERR_FAILURE;
6094 : }
6095 :
6096 : /* -------------------------------------------------------------------- */
6097 : /* Find the named field. */
6098 : /* -------------------------------------------------------------------- */
6099 28 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6100 :
6101 28 : CSLDestroy(papszTokens);
6102 :
6103 28 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6104 : {
6105 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6106 : pszSQLCommand);
6107 0 : return OGRERR_FAILURE;
6108 : }
6109 :
6110 : /* -------------------------------------------------------------------- */
6111 : /* Attempt to create the index. */
6112 : /* -------------------------------------------------------------------- */
6113 28 : OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6114 28 : if (eErr == OGRERR_NONE)
6115 : {
6116 28 : eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6117 : }
6118 : else
6119 : {
6120 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
6121 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6122 : }
6123 :
6124 28 : return eErr;
6125 : }
6126 :
6127 : /************************************************************************/
6128 : /* ProcessSQLDropIndex() */
6129 : /* */
6130 : /* The correct syntax for dropping one or more indexes in */
6131 : /* the OGR SQL dialect is: */
6132 : /* */
6133 : /* DROP INDEX ON <layername> [USING <columnname>] */
6134 : /************************************************************************/
6135 :
6136 10 : OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6137 :
6138 : {
6139 10 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6140 :
6141 : /* -------------------------------------------------------------------- */
6142 : /* Do some general syntax checking. */
6143 : /* -------------------------------------------------------------------- */
6144 20 : if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6145 10 : !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6146 30 : !EQUAL(papszTokens[2], "ON") ||
6147 10 : (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6148 : {
6149 0 : CSLDestroy(papszTokens);
6150 0 : CPLError(CE_Failure, CPLE_AppDefined,
6151 : "Syntax error in DROP INDEX command.\n"
6152 : "Was '%s'\n"
6153 : "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6154 : pszSQLCommand);
6155 0 : return OGRERR_FAILURE;
6156 : }
6157 :
6158 : /* -------------------------------------------------------------------- */
6159 : /* Find the named layer. */
6160 : /* -------------------------------------------------------------------- */
6161 10 : OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6162 10 : if (poLayer == nullptr)
6163 : {
6164 0 : CPLError(CE_Failure, CPLE_AppDefined,
6165 : "DROP INDEX ON failed, no such layer as `%s'.",
6166 0 : papszTokens[3]);
6167 0 : CSLDestroy(papszTokens);
6168 0 : return OGRERR_FAILURE;
6169 : }
6170 :
6171 : /* -------------------------------------------------------------------- */
6172 : /* Does this layer even support attribute indexes? */
6173 : /* -------------------------------------------------------------------- */
6174 10 : if (poLayer->GetIndex() == nullptr)
6175 : {
6176 0 : CPLError(CE_Failure, CPLE_AppDefined,
6177 : "Indexes not supported by this driver.");
6178 0 : CSLDestroy(papszTokens);
6179 0 : return OGRERR_FAILURE;
6180 : }
6181 :
6182 : /* -------------------------------------------------------------------- */
6183 : /* If we were not given a field name, drop all indexes. */
6184 : /* -------------------------------------------------------------------- */
6185 10 : if (CSLCount(papszTokens) == 4)
6186 : {
6187 0 : for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6188 : {
6189 : OGRAttrIndex *poAttrIndex;
6190 :
6191 0 : poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6192 0 : if (poAttrIndex != nullptr)
6193 : {
6194 0 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6195 0 : if (eErr != OGRERR_NONE)
6196 : {
6197 0 : CSLDestroy(papszTokens);
6198 0 : return eErr;
6199 : }
6200 : }
6201 : }
6202 :
6203 0 : CSLDestroy(papszTokens);
6204 0 : return OGRERR_NONE;
6205 : }
6206 :
6207 : /* -------------------------------------------------------------------- */
6208 : /* Find the named field. */
6209 : /* -------------------------------------------------------------------- */
6210 10 : int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6211 10 : CSLDestroy(papszTokens);
6212 :
6213 10 : if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6214 : {
6215 0 : CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6216 : pszSQLCommand);
6217 0 : return OGRERR_FAILURE;
6218 : }
6219 :
6220 : /* -------------------------------------------------------------------- */
6221 : /* Attempt to drop the index. */
6222 : /* -------------------------------------------------------------------- */
6223 10 : const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6224 :
6225 10 : return eErr;
6226 : }
6227 :
6228 : /************************************************************************/
6229 : /* ProcessSQLDropTable() */
6230 : /* */
6231 : /* The correct syntax for dropping a table (layer) in the OGR SQL */
6232 : /* dialect is: */
6233 : /* */
6234 : /* DROP TABLE <layername> */
6235 : /************************************************************************/
6236 :
6237 500 : OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6238 :
6239 : {
6240 500 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6241 :
6242 : /* -------------------------------------------------------------------- */
6243 : /* Do some general syntax checking. */
6244 : /* -------------------------------------------------------------------- */
6245 1000 : if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6246 500 : !EQUAL(papszTokens[1], "TABLE"))
6247 : {
6248 0 : CSLDestroy(papszTokens);
6249 0 : CPLError(CE_Failure, CPLE_AppDefined,
6250 : "Syntax error in DROP TABLE command.\n"
6251 : "Was '%s'\n"
6252 : "Should be of form 'DROP TABLE <table>'",
6253 : pszSQLCommand);
6254 0 : return OGRERR_FAILURE;
6255 : }
6256 :
6257 : /* -------------------------------------------------------------------- */
6258 : /* Find the named layer. */
6259 : /* -------------------------------------------------------------------- */
6260 500 : OGRLayer *poLayer = nullptr;
6261 :
6262 500 : int i = 0; // Used after for.
6263 40199 : for (; i < GetLayerCount(); ++i)
6264 : {
6265 40199 : poLayer = GetLayer(i);
6266 :
6267 40199 : if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6268 500 : break;
6269 39699 : poLayer = nullptr;
6270 : }
6271 :
6272 500 : if (poLayer == nullptr)
6273 : {
6274 0 : CPLError(CE_Failure, CPLE_AppDefined,
6275 0 : "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6276 0 : CSLDestroy(papszTokens);
6277 0 : return OGRERR_FAILURE;
6278 : }
6279 :
6280 500 : CSLDestroy(papszTokens);
6281 :
6282 : /* -------------------------------------------------------------------- */
6283 : /* Delete it. */
6284 : /* -------------------------------------------------------------------- */
6285 :
6286 500 : return DeleteLayer(i);
6287 : }
6288 :
6289 : //! @endcond
6290 :
6291 : /************************************************************************/
6292 : /* GDALDatasetParseSQLType() */
6293 : /************************************************************************/
6294 :
6295 : /* All arguments will be altered */
6296 6 : static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6297 : int &nPrecision)
6298 : {
6299 6 : char *pszParenthesis = strchr(pszType, '(');
6300 6 : if (pszParenthesis)
6301 : {
6302 4 : nWidth = atoi(pszParenthesis + 1);
6303 4 : *pszParenthesis = '\0';
6304 4 : char *pszComma = strchr(pszParenthesis + 1, ',');
6305 4 : if (pszComma)
6306 2 : nPrecision = atoi(pszComma + 1);
6307 : }
6308 :
6309 6 : OGRFieldType eType = OFTString;
6310 6 : if (EQUAL(pszType, "INTEGER"))
6311 0 : eType = OFTInteger;
6312 6 : else if (EQUAL(pszType, "INTEGER[]"))
6313 0 : eType = OFTIntegerList;
6314 6 : else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6315 4 : EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6316 4 : EQUAL(pszType, "REAL") /* unofficial alias */)
6317 2 : eType = OFTReal;
6318 4 : else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6319 4 : EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6320 4 : EQUAL(pszType, "REAL[]") /* unofficial alias */)
6321 0 : eType = OFTRealList;
6322 4 : else if (EQUAL(pszType, "CHARACTER") ||
6323 0 : EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6324 0 : EQUAL(pszType, "STRING") /* unofficial alias */ ||
6325 0 : EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6326 4 : eType = OFTString;
6327 0 : else if (EQUAL(pszType, "TEXT[]") ||
6328 0 : EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6329 0 : EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6330 0 : eType = OFTStringList;
6331 0 : else if (EQUAL(pszType, "DATE"))
6332 0 : eType = OFTDate;
6333 0 : else if (EQUAL(pszType, "TIME"))
6334 0 : eType = OFTTime;
6335 0 : else if (EQUAL(pszType, "TIMESTAMP") ||
6336 0 : EQUAL(pszType, "DATETIME") /* unofficial alias */)
6337 0 : eType = OFTDateTime;
6338 : else
6339 0 : CPLError(CE_Warning, CPLE_NotSupported,
6340 : "Unsupported column type '%s'. Defaulting to VARCHAR",
6341 : pszType);
6342 :
6343 6 : return eType;
6344 : }
6345 :
6346 : /************************************************************************/
6347 : /* ProcessSQLAlterTableAddColumn() */
6348 : /* */
6349 : /* The correct syntax for adding a column in the OGR SQL */
6350 : /* dialect is: */
6351 : /* */
6352 : /* ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6353 : /************************************************************************/
6354 :
6355 : //! @cond Doxygen_Suppress
6356 2 : OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6357 :
6358 : {
6359 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6360 :
6361 : /* -------------------------------------------------------------------- */
6362 : /* Do some general syntax checking. */
6363 : /* -------------------------------------------------------------------- */
6364 2 : const char *pszLayerName = nullptr;
6365 2 : const char *pszColumnName = nullptr;
6366 2 : int iTypeIndex = 0;
6367 2 : const int nTokens = CSLCount(papszTokens);
6368 :
6369 2 : if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6370 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6371 2 : EQUAL(papszTokens[4], "COLUMN"))
6372 : {
6373 1 : pszLayerName = papszTokens[2];
6374 1 : pszColumnName = papszTokens[5];
6375 1 : iTypeIndex = 6;
6376 : }
6377 1 : else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6378 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6379 : {
6380 1 : pszLayerName = papszTokens[2];
6381 1 : pszColumnName = papszTokens[4];
6382 1 : iTypeIndex = 5;
6383 : }
6384 : else
6385 : {
6386 0 : CSLDestroy(papszTokens);
6387 0 : CPLError(CE_Failure, CPLE_AppDefined,
6388 : "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6389 : "Was '%s'\n"
6390 : "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6391 : "<columnname> <columntype>'",
6392 : pszSQLCommand);
6393 0 : return OGRERR_FAILURE;
6394 : }
6395 :
6396 : /* -------------------------------------------------------------------- */
6397 : /* Merge type components into a single string if there were split */
6398 : /* with spaces */
6399 : /* -------------------------------------------------------------------- */
6400 4 : CPLString osType;
6401 6 : for (int i = iTypeIndex; i < nTokens; ++i)
6402 : {
6403 4 : osType += papszTokens[i];
6404 4 : CPLFree(papszTokens[i]);
6405 : }
6406 2 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6407 2 : papszTokens[iTypeIndex + 1] = nullptr;
6408 :
6409 : /* -------------------------------------------------------------------- */
6410 : /* Find the named layer. */
6411 : /* -------------------------------------------------------------------- */
6412 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6413 2 : if (poLayer == nullptr)
6414 : {
6415 0 : CPLError(CE_Failure, CPLE_AppDefined,
6416 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6417 : pszLayerName);
6418 0 : CSLDestroy(papszTokens);
6419 0 : return OGRERR_FAILURE;
6420 : }
6421 :
6422 : /* -------------------------------------------------------------------- */
6423 : /* Add column. */
6424 : /* -------------------------------------------------------------------- */
6425 :
6426 2 : int nWidth = 0;
6427 2 : int nPrecision = 0;
6428 2 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6429 4 : OGRFieldDefn oFieldDefn(pszColumnName, eType);
6430 2 : oFieldDefn.SetWidth(nWidth);
6431 2 : oFieldDefn.SetPrecision(nPrecision);
6432 :
6433 2 : CSLDestroy(papszTokens);
6434 :
6435 2 : return poLayer->CreateField(&oFieldDefn);
6436 : }
6437 :
6438 : /************************************************************************/
6439 : /* ProcessSQLAlterTableDropColumn() */
6440 : /* */
6441 : /* The correct syntax for dropping a column in the OGR SQL */
6442 : /* dialect is: */
6443 : /* */
6444 : /* ALTER TABLE <layername> DROP [COLUMN] <columnname> */
6445 : /************************************************************************/
6446 :
6447 2 : OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6448 :
6449 : {
6450 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6451 :
6452 : /* -------------------------------------------------------------------- */
6453 : /* Do some general syntax checking. */
6454 : /* -------------------------------------------------------------------- */
6455 2 : const char *pszLayerName = nullptr;
6456 2 : const char *pszColumnName = nullptr;
6457 3 : if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6458 4 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6459 1 : EQUAL(papszTokens[4], "COLUMN"))
6460 : {
6461 1 : pszLayerName = papszTokens[2];
6462 1 : pszColumnName = papszTokens[5];
6463 : }
6464 2 : else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6465 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6466 : {
6467 1 : pszLayerName = papszTokens[2];
6468 1 : pszColumnName = papszTokens[4];
6469 : }
6470 : else
6471 : {
6472 0 : CSLDestroy(papszTokens);
6473 0 : CPLError(CE_Failure, CPLE_AppDefined,
6474 : "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6475 : "Was '%s'\n"
6476 : "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6477 : "<columnname>'",
6478 : pszSQLCommand);
6479 0 : return OGRERR_FAILURE;
6480 : }
6481 :
6482 : /* -------------------------------------------------------------------- */
6483 : /* Find the named layer. */
6484 : /* -------------------------------------------------------------------- */
6485 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6486 2 : if (poLayer == nullptr)
6487 : {
6488 0 : CPLError(CE_Failure, CPLE_AppDefined,
6489 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6490 : pszLayerName);
6491 0 : CSLDestroy(papszTokens);
6492 0 : return OGRERR_FAILURE;
6493 : }
6494 :
6495 : /* -------------------------------------------------------------------- */
6496 : /* Find the field. */
6497 : /* -------------------------------------------------------------------- */
6498 :
6499 2 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6500 2 : if (nFieldIndex < 0)
6501 : {
6502 0 : CPLError(CE_Failure, CPLE_AppDefined,
6503 : "%s failed, no such field as `%s'.", pszSQLCommand,
6504 : pszColumnName);
6505 0 : CSLDestroy(papszTokens);
6506 0 : return OGRERR_FAILURE;
6507 : }
6508 :
6509 : /* -------------------------------------------------------------------- */
6510 : /* Remove it. */
6511 : /* -------------------------------------------------------------------- */
6512 :
6513 2 : CSLDestroy(papszTokens);
6514 :
6515 2 : return poLayer->DeleteField(nFieldIndex);
6516 : }
6517 :
6518 : /************************************************************************/
6519 : /* ProcessSQLAlterTableRenameColumn() */
6520 : /* */
6521 : /* The correct syntax for renaming a column in the OGR SQL */
6522 : /* dialect is: */
6523 : /* */
6524 : /* ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6525 : /************************************************************************/
6526 :
6527 2 : OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6528 :
6529 : {
6530 2 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6531 :
6532 : /* -------------------------------------------------------------------- */
6533 : /* Do some general syntax checking. */
6534 : /* -------------------------------------------------------------------- */
6535 2 : const char *pszLayerName = nullptr;
6536 2 : const char *pszOldColName = nullptr;
6537 2 : const char *pszNewColName = nullptr;
6538 3 : if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6539 1 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6540 3 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6541 : {
6542 1 : pszLayerName = papszTokens[2];
6543 1 : pszOldColName = papszTokens[5];
6544 1 : pszNewColName = papszTokens[7];
6545 : }
6546 2 : else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6547 1 : EQUAL(papszTokens[1], "TABLE") &&
6548 2 : EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6549 : {
6550 1 : pszLayerName = papszTokens[2];
6551 1 : pszOldColName = papszTokens[4];
6552 1 : pszNewColName = papszTokens[6];
6553 : }
6554 : else
6555 : {
6556 0 : CSLDestroy(papszTokens);
6557 0 : CPLError(CE_Failure, CPLE_AppDefined,
6558 : "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6559 : "Was '%s'\n"
6560 : "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6561 : "<columnname> TO <newname>'",
6562 : pszSQLCommand);
6563 0 : return OGRERR_FAILURE;
6564 : }
6565 :
6566 : /* -------------------------------------------------------------------- */
6567 : /* Find the named layer. */
6568 : /* -------------------------------------------------------------------- */
6569 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6570 2 : if (poLayer == nullptr)
6571 : {
6572 0 : CPLError(CE_Failure, CPLE_AppDefined,
6573 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6574 : pszLayerName);
6575 0 : CSLDestroy(papszTokens);
6576 0 : return OGRERR_FAILURE;
6577 : }
6578 :
6579 : /* -------------------------------------------------------------------- */
6580 : /* Find the field. */
6581 : /* -------------------------------------------------------------------- */
6582 :
6583 : const int nFieldIndex =
6584 2 : poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6585 2 : if (nFieldIndex < 0)
6586 : {
6587 0 : CPLError(CE_Failure, CPLE_AppDefined,
6588 : "%s failed, no such field as `%s'.", pszSQLCommand,
6589 : pszOldColName);
6590 0 : CSLDestroy(papszTokens);
6591 0 : return OGRERR_FAILURE;
6592 : }
6593 :
6594 : /* -------------------------------------------------------------------- */
6595 : /* Rename column. */
6596 : /* -------------------------------------------------------------------- */
6597 : OGRFieldDefn *poOldFieldDefn =
6598 2 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6599 4 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6600 2 : oNewFieldDefn.SetName(pszNewColName);
6601 :
6602 2 : CSLDestroy(papszTokens);
6603 :
6604 2 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6605 2 : ALTER_NAME_FLAG);
6606 : }
6607 :
6608 : /************************************************************************/
6609 : /* ProcessSQLAlterTableAlterColumn() */
6610 : /* */
6611 : /* The correct syntax for altering the type of a column in the */
6612 : /* OGR SQL dialect is: */
6613 : /* */
6614 : /* ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6615 : /************************************************************************/
6616 :
6617 4 : OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
6618 :
6619 : {
6620 4 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
6621 :
6622 : /* -------------------------------------------------------------------- */
6623 : /* Do some general syntax checking. */
6624 : /* -------------------------------------------------------------------- */
6625 4 : const char *pszLayerName = nullptr;
6626 4 : const char *pszColumnName = nullptr;
6627 4 : int iTypeIndex = 0;
6628 4 : const int nTokens = CSLCount(papszTokens);
6629 :
6630 4 : if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
6631 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6632 2 : EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
6633 : {
6634 2 : pszLayerName = papszTokens[2];
6635 2 : pszColumnName = papszTokens[5];
6636 2 : iTypeIndex = 7;
6637 : }
6638 2 : else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6639 2 : EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6640 2 : EQUAL(papszTokens[5], "TYPE"))
6641 : {
6642 2 : pszLayerName = papszTokens[2];
6643 2 : pszColumnName = papszTokens[4];
6644 2 : iTypeIndex = 6;
6645 : }
6646 : else
6647 : {
6648 0 : CSLDestroy(papszTokens);
6649 0 : CPLError(CE_Failure, CPLE_AppDefined,
6650 : "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6651 : "Was '%s'\n"
6652 : "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6653 : "<columnname> TYPE <columntype>'",
6654 : pszSQLCommand);
6655 0 : return OGRERR_FAILURE;
6656 : }
6657 :
6658 : /* -------------------------------------------------------------------- */
6659 : /* Merge type components into a single string if there were split */
6660 : /* with spaces */
6661 : /* -------------------------------------------------------------------- */
6662 8 : CPLString osType;
6663 8 : for (int i = iTypeIndex; i < nTokens; ++i)
6664 : {
6665 4 : osType += papszTokens[i];
6666 4 : CPLFree(papszTokens[i]);
6667 : }
6668 4 : char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6669 4 : papszTokens[iTypeIndex + 1] = nullptr;
6670 :
6671 : /* -------------------------------------------------------------------- */
6672 : /* Find the named layer. */
6673 : /* -------------------------------------------------------------------- */
6674 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
6675 4 : if (poLayer == nullptr)
6676 : {
6677 0 : CPLError(CE_Failure, CPLE_AppDefined,
6678 : "%s failed, no such layer as `%s'.", pszSQLCommand,
6679 : pszLayerName);
6680 0 : CSLDestroy(papszTokens);
6681 0 : return OGRERR_FAILURE;
6682 : }
6683 :
6684 : /* -------------------------------------------------------------------- */
6685 : /* Find the field. */
6686 : /* -------------------------------------------------------------------- */
6687 :
6688 : const int nFieldIndex =
6689 4 : poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6690 4 : if (nFieldIndex < 0)
6691 : {
6692 0 : CPLError(CE_Failure, CPLE_AppDefined,
6693 : "%s failed, no such field as `%s'.", pszSQLCommand,
6694 : pszColumnName);
6695 0 : CSLDestroy(papszTokens);
6696 0 : return OGRERR_FAILURE;
6697 : }
6698 :
6699 : /* -------------------------------------------------------------------- */
6700 : /* Alter column. */
6701 : /* -------------------------------------------------------------------- */
6702 :
6703 : OGRFieldDefn *poOldFieldDefn =
6704 4 : poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6705 8 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6706 :
6707 4 : int nWidth = 0;
6708 4 : int nPrecision = 0;
6709 4 : OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6710 4 : oNewFieldDefn.SetType(eType);
6711 4 : oNewFieldDefn.SetWidth(nWidth);
6712 4 : oNewFieldDefn.SetPrecision(nPrecision);
6713 :
6714 4 : int l_nFlags = 0;
6715 4 : if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6716 2 : l_nFlags |= ALTER_TYPE_FLAG;
6717 4 : if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6718 0 : poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6719 4 : l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6720 :
6721 4 : CSLDestroy(papszTokens);
6722 :
6723 4 : if (l_nFlags == 0)
6724 0 : return OGRERR_NONE;
6725 :
6726 4 : return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6727 : }
6728 :
6729 : //! @endcond
6730 :
6731 : /************************************************************************/
6732 : /* ExecuteSQL() */
6733 : /************************************************************************/
6734 :
6735 : /**
6736 : \brief Execute an SQL statement against the data store.
6737 :
6738 : The result of an SQL query is either NULL for statements that are in error,
6739 : or that have no results set, or an OGRLayer pointer representing a results
6740 : set from the query. Note that this OGRLayer is in addition to the layers
6741 : in the data store and must be destroyed with
6742 : ReleaseResultSet() before the dataset is closed
6743 : (destroyed).
6744 :
6745 : This method is the same as the C function GDALDatasetExecuteSQL() and the
6746 : deprecated OGR_DS_ExecuteSQL().
6747 :
6748 : For more information on the SQL dialect supported internally by OGR
6749 : review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
6750 : document. Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
6751 : to the underlying RDBMS.
6752 :
6753 : Starting with OGR 1.10, the <a
6754 : href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
6755 : also be used.
6756 :
6757 : In GDAL 1.X, this method used to be in the OGRDataSource class.
6758 :
6759 : @param pszStatement the SQL statement to execute.
6760 : @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6761 : @param pszDialect allows control of the statement dialect. If set to NULL, the
6762 : OGR SQL engine will be used, except for RDBMS drivers that will use their
6763 : dedicated SQL engine, unless OGRSQL is explicitly passed as the
6764 : dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
6765 :
6766 : @return an OGRLayer containing the results of the query. Deallocate with
6767 : ReleaseResultSet().
6768 :
6769 : */
6770 :
6771 3300 : OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
6772 : OGRGeometry *poSpatialFilter,
6773 : const char *pszDialect)
6774 :
6775 : {
6776 3300 : return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
6777 : }
6778 :
6779 : //! @cond Doxygen_Suppress
6780 : OGRLayer *
6781 3308 : GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
6782 : const char *pszDialect,
6783 : swq_select_parse_options *poSelectParseOptions)
6784 :
6785 : {
6786 3308 : if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
6787 : {
6788 : #ifdef SQLITE_ENABLED
6789 572 : return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
6790 572 : pszDialect);
6791 : #else
6792 : CPLError(CE_Failure, CPLE_NotSupported,
6793 : "The SQLite driver needs to be compiled to support the "
6794 : "SQLite SQL dialect");
6795 : return nullptr;
6796 : #endif
6797 : }
6798 :
6799 2736 : if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
6800 11 : !EQUAL(pszDialect, "OGRSQL"))
6801 : {
6802 2 : std::string osDialectList = "'OGRSQL'";
6803 : #ifdef SQLITE_ENABLED
6804 1 : osDialectList += ", 'SQLITE'";
6805 : #endif
6806 : const char *pszDialects =
6807 1 : GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
6808 1 : if (pszDialects)
6809 : {
6810 : const CPLStringList aosTokens(
6811 0 : CSLTokenizeString2(pszDialects, " ", 0));
6812 0 : for (int i = 0; i < aosTokens.size(); ++i)
6813 : {
6814 0 : if (!EQUAL(aosTokens[i], "OGRSQL") &&
6815 0 : !EQUAL(aosTokens[i], "SQLITE"))
6816 : {
6817 0 : osDialectList += ", '";
6818 0 : osDialectList += aosTokens[i];
6819 0 : osDialectList += "'";
6820 : }
6821 : }
6822 : }
6823 1 : CPLError(CE_Warning, CPLE_NotSupported,
6824 : "Dialect '%s' is unsupported. Only supported dialects are %s. "
6825 : "Defaulting to OGRSQL",
6826 : pszDialect, osDialectList.c_str());
6827 : }
6828 :
6829 : /* -------------------------------------------------------------------- */
6830 : /* Handle CREATE INDEX statements specially. */
6831 : /* -------------------------------------------------------------------- */
6832 2736 : if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
6833 : {
6834 28 : ProcessSQLCreateIndex(pszStatement);
6835 28 : return nullptr;
6836 : }
6837 :
6838 : /* -------------------------------------------------------------------- */
6839 : /* Handle DROP INDEX statements specially. */
6840 : /* -------------------------------------------------------------------- */
6841 2708 : if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
6842 : {
6843 10 : ProcessSQLDropIndex(pszStatement);
6844 10 : return nullptr;
6845 : }
6846 :
6847 : /* -------------------------------------------------------------------- */
6848 : /* Handle DROP TABLE statements specially. */
6849 : /* -------------------------------------------------------------------- */
6850 2698 : if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
6851 : {
6852 500 : ProcessSQLDropTable(pszStatement);
6853 500 : return nullptr;
6854 : }
6855 :
6856 : /* -------------------------------------------------------------------- */
6857 : /* Handle ALTER TABLE statements specially. */
6858 : /* -------------------------------------------------------------------- */
6859 2198 : if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
6860 : {
6861 11 : char **papszTokens = CSLTokenizeString(pszStatement);
6862 11 : const int nTokens = CSLCount(papszTokens);
6863 11 : if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
6864 : {
6865 2 : ProcessSQLAlterTableAddColumn(pszStatement);
6866 2 : CSLDestroy(papszTokens);
6867 2 : return nullptr;
6868 : }
6869 9 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
6870 : {
6871 2 : ProcessSQLAlterTableDropColumn(pszStatement);
6872 2 : CSLDestroy(papszTokens);
6873 2 : return nullptr;
6874 : }
6875 7 : else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
6876 1 : EQUAL(papszTokens[4], "TO"))
6877 : {
6878 1 : const char *pszSrcTableName = papszTokens[2];
6879 1 : const char *pszDstTableName = papszTokens[5];
6880 1 : auto poSrcLayer = GetLayerByName(pszSrcTableName);
6881 1 : if (poSrcLayer)
6882 : {
6883 1 : CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
6884 : }
6885 : else
6886 : {
6887 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
6888 : }
6889 1 : CSLDestroy(papszTokens);
6890 1 : return nullptr;
6891 : }
6892 6 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
6893 : {
6894 2 : ProcessSQLAlterTableRenameColumn(pszStatement);
6895 2 : CSLDestroy(papszTokens);
6896 2 : return nullptr;
6897 : }
6898 4 : else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
6899 : {
6900 4 : ProcessSQLAlterTableAlterColumn(pszStatement);
6901 4 : CSLDestroy(papszTokens);
6902 4 : return nullptr;
6903 : }
6904 : else
6905 : {
6906 0 : CPLError(CE_Failure, CPLE_AppDefined,
6907 : "Unsupported ALTER TABLE command : %s", pszStatement);
6908 0 : CSLDestroy(papszTokens);
6909 0 : return nullptr;
6910 : }
6911 : }
6912 :
6913 : /* -------------------------------------------------------------------- */
6914 : /* Preparse the SQL statement. */
6915 : /* -------------------------------------------------------------------- */
6916 2187 : swq_select *psSelectInfo = new swq_select();
6917 2187 : swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
6918 2187 : if (poSelectParseOptions != nullptr)
6919 8 : poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
6920 2187 : if (psSelectInfo->preparse(pszStatement,
6921 2187 : poCustomFuncRegistrar != nullptr) != CE_None)
6922 : {
6923 199 : delete psSelectInfo;
6924 199 : return nullptr;
6925 : }
6926 :
6927 : /* -------------------------------------------------------------------- */
6928 : /* If there is no UNION ALL, build result layer. */
6929 : /* -------------------------------------------------------------------- */
6930 1988 : if (psSelectInfo->poOtherSelect == nullptr)
6931 : {
6932 1983 : return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
6933 1983 : pszDialect, poSelectParseOptions);
6934 : }
6935 :
6936 : /* -------------------------------------------------------------------- */
6937 : /* Build result union layer. */
6938 : /* -------------------------------------------------------------------- */
6939 5 : int nSrcLayers = 0;
6940 5 : OGRLayer **papoSrcLayers = nullptr;
6941 :
6942 5 : do
6943 : {
6944 10 : swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
6945 10 : psSelectInfo->poOtherSelect = nullptr;
6946 :
6947 10 : OGRLayer *poLayer = BuildLayerFromSelectInfo(
6948 : psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
6949 10 : if (poLayer == nullptr)
6950 : {
6951 : // Each source layer owns an independent select info.
6952 0 : for (int i = 0; i < nSrcLayers; ++i)
6953 0 : delete papoSrcLayers[i];
6954 0 : CPLFree(papoSrcLayers);
6955 :
6956 : // So we just have to destroy the remaining select info.
6957 0 : delete psNextSelectInfo;
6958 :
6959 0 : return nullptr;
6960 : }
6961 : else
6962 : {
6963 20 : papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
6964 10 : papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
6965 10 : papoSrcLayers[nSrcLayers] = poLayer;
6966 10 : ++nSrcLayers;
6967 :
6968 10 : psSelectInfo = psNextSelectInfo;
6969 : }
6970 10 : } while (psSelectInfo != nullptr);
6971 :
6972 5 : return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
6973 : }
6974 :
6975 : //! @endcond
6976 :
6977 : /************************************************************************/
6978 : /* AbortSQL() */
6979 : /************************************************************************/
6980 :
6981 : /**
6982 : \brief Abort any SQL statement running in the data store.
6983 :
6984 : This function can be safely called from any thread (pending that the dataset
6985 : object is still alive). Driver implementations will make sure that it can be
6986 : called in a thread-safe way.
6987 :
6988 : This might not be implemented by all drivers. At time of writing, only SQLite,
6989 : GPKG and PG drivers implement it
6990 :
6991 : This method is the same as the C method GDALDatasetAbortSQL()
6992 :
6993 : @since GDAL 3.2.0
6994 :
6995 :
6996 : */
6997 :
6998 0 : OGRErr GDALDataset::AbortSQL()
6999 : {
7000 0 : CPLError(CE_Failure, CPLE_NotSupported,
7001 : "AbortSQL is not supported for this driver.");
7002 0 : return OGRERR_UNSUPPORTED_OPERATION;
7003 : }
7004 :
7005 : /************************************************************************/
7006 : /* BuildLayerFromSelectInfo() */
7007 : /************************************************************************/
7008 :
7009 : struct GDALSQLParseInfo
7010 : {
7011 : swq_field_list sFieldList;
7012 : int nExtraDSCount;
7013 : GDALDataset **papoExtraDS;
7014 : char *pszWHERE;
7015 : };
7016 :
7017 1993 : OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7018 : swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7019 : const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7020 : {
7021 1993 : std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7022 : GDALSQLParseInfo *psParseInfo =
7023 1993 : BuildParseInfo(psSelectInfo, poSelectParseOptions);
7024 :
7025 1993 : if (psParseInfo)
7026 : {
7027 1932 : const auto nErrorCounter = CPLGetErrorCounter();
7028 1932 : poResults = std::make_unique<OGRGenSQLResultsLayer>(
7029 1932 : this, psSelectInfo, poSpatialFilter, psParseInfo->pszWHERE,
7030 1932 : pszDialect);
7031 2007 : if (CPLGetErrorCounter() > nErrorCounter &&
7032 75 : CPLGetLastErrorType() != CE_None)
7033 75 : poResults.reset();
7034 : }
7035 : else
7036 : {
7037 61 : delete psSelectInfo;
7038 : }
7039 1993 : DestroyParseInfo(psParseInfo);
7040 :
7041 3986 : return poResults.release();
7042 : }
7043 :
7044 : /************************************************************************/
7045 : /* DestroyParseInfo() */
7046 : /************************************************************************/
7047 :
7048 : //! @cond Doxygen_Suppress
7049 2088 : void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7050 : {
7051 2088 : if (psParseInfo == nullptr)
7052 61 : return;
7053 :
7054 2027 : CPLFree(psParseInfo->sFieldList.names);
7055 2027 : CPLFree(psParseInfo->sFieldList.types);
7056 2027 : CPLFree(psParseInfo->sFieldList.table_ids);
7057 2027 : CPLFree(psParseInfo->sFieldList.ids);
7058 :
7059 : // Release the datasets we have opened with OGROpenShared()
7060 : // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7061 : // has taken a reference on them, which it will release in its
7062 : // destructor.
7063 2034 : for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7064 7 : GDALClose(psParseInfo->papoExtraDS[iEDS]);
7065 :
7066 2027 : CPLFree(psParseInfo->papoExtraDS);
7067 2027 : CPLFree(psParseInfo->pszWHERE);
7068 2027 : CPLFree(psParseInfo);
7069 : }
7070 :
7071 : /************************************************************************/
7072 : /* BuildParseInfo() */
7073 : /************************************************************************/
7074 :
7075 : GDALSQLParseInfo *
7076 2027 : GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7077 : swq_select_parse_options *poSelectParseOptions)
7078 : {
7079 2027 : int nFirstLayerFirstSpecialFieldIndex = 0;
7080 :
7081 : GDALSQLParseInfo *psParseInfo =
7082 2027 : static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7083 :
7084 : /* -------------------------------------------------------------------- */
7085 : /* Validate that all the source tables are recognized, count */
7086 : /* fields. */
7087 : /* -------------------------------------------------------------------- */
7088 2027 : int nFieldCount = 0;
7089 :
7090 4119 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7091 : {
7092 2098 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7093 2098 : GDALDataset *poTableDS = this;
7094 :
7095 2098 : if (psTableDef->data_source != nullptr)
7096 : {
7097 7 : poTableDS = GDALDataset::FromHandle(
7098 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7099 7 : if (poTableDS == nullptr)
7100 : {
7101 0 : if (strlen(CPLGetLastErrorMsg()) == 0)
7102 0 : CPLError(CE_Failure, CPLE_AppDefined,
7103 : "Unable to open secondary datasource "
7104 : "`%s' required by JOIN.",
7105 : psTableDef->data_source);
7106 :
7107 0 : DestroyParseInfo(psParseInfo);
7108 0 : return nullptr;
7109 : }
7110 :
7111 : // Keep in an array to release at the end of this function.
7112 14 : psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7113 7 : psParseInfo->papoExtraDS,
7114 7 : sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7115 7 : psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7116 : }
7117 :
7118 : OGRLayer *poSrcLayer =
7119 2098 : poTableDS->GetLayerByName(psTableDef->table_name);
7120 :
7121 2098 : if (poSrcLayer == nullptr)
7122 : {
7123 6 : CPLError(CE_Failure, CPLE_AppDefined,
7124 : "SELECT from table %s failed, no such table/featureclass.",
7125 : psTableDef->table_name);
7126 :
7127 6 : DestroyParseInfo(psParseInfo);
7128 6 : return nullptr;
7129 : }
7130 :
7131 2092 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7132 2092 : if (iTable == 0 ||
7133 34 : (poSelectParseOptions &&
7134 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7135 2056 : nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7136 :
7137 2092 : const char *pszFID = poSrcLayer->GetFIDColumn();
7138 2656 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7139 564 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7140 514 : nFieldCount++;
7141 : }
7142 :
7143 : /* -------------------------------------------------------------------- */
7144 : /* Build the field list for all indicated tables. */
7145 : /* -------------------------------------------------------------------- */
7146 :
7147 2021 : psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7148 2021 : psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7149 :
7150 2021 : psParseInfo->sFieldList.count = 0;
7151 2021 : psParseInfo->sFieldList.names = static_cast<char **>(
7152 2021 : CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7153 4042 : psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7154 2021 : sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7155 2021 : psParseInfo->sFieldList.table_ids = static_cast<int *>(
7156 2021 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7157 2021 : psParseInfo->sFieldList.ids = static_cast<int *>(
7158 2021 : CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7159 :
7160 2021 : bool bIsFID64 = false;
7161 4112 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7162 : {
7163 2091 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7164 2091 : GDALDataset *poTableDS = this;
7165 :
7166 2091 : if (psTableDef->data_source != nullptr)
7167 : {
7168 7 : poTableDS = GDALDataset::FromHandle(
7169 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7170 7 : CPLAssert(poTableDS != nullptr);
7171 7 : poTableDS->Dereference();
7172 : }
7173 :
7174 : OGRLayer *poSrcLayer =
7175 2091 : poTableDS->GetLayerByName(psTableDef->table_name);
7176 :
7177 2091 : for (int iField = 0;
7178 17626 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7179 : {
7180 : OGRFieldDefn *poFDefn =
7181 15535 : poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7182 15535 : const int iOutField = psParseInfo->sFieldList.count++;
7183 31070 : psParseInfo->sFieldList.names[iOutField] =
7184 15535 : const_cast<char *>(poFDefn->GetNameRef());
7185 15535 : if (poFDefn->GetType() == OFTInteger)
7186 : {
7187 4058 : if (poFDefn->GetSubType() == OFSTBoolean)
7188 155 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7189 : else
7190 3903 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7191 : }
7192 11477 : else if (poFDefn->GetType() == OFTInteger64)
7193 : {
7194 707 : if (poFDefn->GetSubType() == OFSTBoolean)
7195 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7196 : else
7197 707 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7198 : }
7199 10770 : else if (poFDefn->GetType() == OFTReal)
7200 2514 : psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7201 8256 : else if (poFDefn->GetType() == OFTString)
7202 5288 : psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7203 2968 : else if (poFDefn->GetType() == OFTTime)
7204 83 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7205 2885 : else if (poFDefn->GetType() == OFTDate)
7206 143 : psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7207 2742 : else if (poFDefn->GetType() == OFTDateTime)
7208 853 : psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7209 : else
7210 1889 : psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7211 :
7212 15535 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7213 15535 : psParseInfo->sFieldList.ids[iOutField] = iField;
7214 : }
7215 :
7216 2091 : if (iTable == 0)
7217 : {
7218 2021 : nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7219 : }
7220 :
7221 2091 : if (iTable == 0 ||
7222 34 : (poSelectParseOptions &&
7223 34 : poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7224 : {
7225 :
7226 2055 : for (int iField = 0;
7227 3770 : iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7228 : iField++)
7229 : {
7230 : OGRGeomFieldDefn *poFDefn =
7231 1715 : poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7232 1715 : const int iOutField = psParseInfo->sFieldList.count++;
7233 3430 : psParseInfo->sFieldList.names[iOutField] =
7234 1715 : const_cast<char *>(poFDefn->GetNameRef());
7235 1715 : if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7236 924 : psParseInfo->sFieldList.names[iOutField] =
7237 : const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7238 1715 : psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7239 :
7240 1715 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7241 1715 : psParseInfo->sFieldList.ids[iOutField] =
7242 1715 : GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7243 : poSrcLayer->GetLayerDefn(), iField);
7244 : }
7245 : }
7246 :
7247 2092 : if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7248 1 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7249 : {
7250 1 : bIsFID64 = true;
7251 : }
7252 : }
7253 :
7254 : /* -------------------------------------------------------------------- */
7255 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
7256 : /* -------------------------------------------------------------------- */
7257 2021 : const bool bAlwaysPrefixWithTableName =
7258 2063 : poSelectParseOptions &&
7259 42 : poSelectParseOptions->bAlwaysPrefixWithTableName;
7260 2021 : if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7261 2021 : bAlwaysPrefixWithTableName) != CE_None)
7262 : {
7263 2 : DestroyParseInfo(psParseInfo);
7264 2 : return nullptr;
7265 : }
7266 :
7267 12114 : for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7268 : {
7269 10095 : psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7270 10095 : const_cast<char *>(SpecialFieldNames[iField]);
7271 10095 : psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7272 10095 : (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7273 : : SpecialFieldTypes[iField];
7274 10095 : psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7275 10095 : psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7276 10095 : nFirstLayerFirstSpecialFieldIndex + iField;
7277 10095 : psParseInfo->sFieldList.count++;
7278 : }
7279 :
7280 : /* In the case a layer has an explicit FID column name, then add it */
7281 : /* so it can be selected */
7282 4108 : for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7283 : {
7284 2089 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7285 2089 : GDALDataset *poTableDS = this;
7286 :
7287 2089 : if (psTableDef->data_source != nullptr)
7288 : {
7289 7 : poTableDS = GDALDataset::FromHandle(
7290 7 : OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7291 7 : CPLAssert(poTableDS != nullptr);
7292 7 : poTableDS->Dereference();
7293 : }
7294 :
7295 : OGRLayer *poSrcLayer =
7296 2089 : poTableDS->GetLayerByName(psTableDef->table_name);
7297 :
7298 2089 : const char *pszFID = poSrcLayer->GetFIDColumn();
7299 2653 : if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7300 564 : poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7301 : {
7302 514 : const int iOutField = psParseInfo->sFieldList.count++;
7303 514 : psParseInfo->sFieldList.names[iOutField] =
7304 : const_cast<char *>(pszFID);
7305 514 : if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7306 0 : EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7307 : {
7308 0 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7309 : }
7310 : else
7311 : {
7312 514 : psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7313 : }
7314 514 : psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7315 1028 : psParseInfo->sFieldList.ids[iOutField] =
7316 514 : poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7317 : }
7318 : }
7319 :
7320 : /* -------------------------------------------------------------------- */
7321 : /* Finish the parse operation. */
7322 : /* -------------------------------------------------------------------- */
7323 2019 : if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7324 : CE_None)
7325 : {
7326 53 : DestroyParseInfo(psParseInfo);
7327 53 : return nullptr;
7328 : }
7329 :
7330 : /* -------------------------------------------------------------------- */
7331 : /* Extract the WHERE expression to use separately. */
7332 : /* -------------------------------------------------------------------- */
7333 1966 : if (psSelectInfo->where_expr != nullptr)
7334 : {
7335 840 : psParseInfo->pszWHERE =
7336 840 : psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7337 : // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7338 : }
7339 :
7340 1966 : return psParseInfo;
7341 : }
7342 :
7343 : //! @endcond
7344 :
7345 : /************************************************************************/
7346 : /* ReleaseResultSet() */
7347 : /************************************************************************/
7348 :
7349 : /**
7350 : \brief Release results of ExecuteSQL().
7351 :
7352 : This method should only be used to deallocate OGRLayers resulting from
7353 : an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a
7354 : results set before destroying the GDALDataset may cause errors.
7355 :
7356 : This method is the same as the C function GDALDatasetReleaseResultSet() and the
7357 : deprecated OGR_DS_ReleaseResultSet().
7358 :
7359 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7360 :
7361 : @param poResultsSet the result of a previous ExecuteSQL() call.
7362 : */
7363 :
7364 1856 : void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7365 :
7366 : {
7367 1856 : delete poResultsSet;
7368 1856 : }
7369 :
7370 : /************************************************************************/
7371 : /* GetStyleTable() */
7372 : /************************************************************************/
7373 :
7374 : /**
7375 : \brief Returns dataset style table.
7376 :
7377 : This method is the same as the C function GDALDatasetGetStyleTable() and the
7378 : deprecated OGR_DS_GetStyleTable().
7379 :
7380 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7381 :
7382 : @return pointer to a style table which should not be modified or freed by the
7383 : caller.
7384 : */
7385 :
7386 631 : OGRStyleTable *GDALDataset::GetStyleTable()
7387 : {
7388 631 : return m_poStyleTable;
7389 : }
7390 :
7391 : /************************************************************************/
7392 : /* SetStyleTableDirectly() */
7393 : /************************************************************************/
7394 :
7395 : /**
7396 : \brief Set dataset style table.
7397 :
7398 : This method operate exactly as SetStyleTable() except that it
7399 : assumes ownership of the passed table.
7400 :
7401 : This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7402 : and the deprecated OGR_DS_SetStyleTableDirectly().
7403 :
7404 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7405 :
7406 : @param poStyleTable pointer to style table to set
7407 :
7408 : */
7409 0 : void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7410 : {
7411 0 : if (m_poStyleTable)
7412 0 : delete m_poStyleTable;
7413 0 : m_poStyleTable = poStyleTable;
7414 0 : }
7415 :
7416 : /************************************************************************/
7417 : /* SetStyleTable() */
7418 : /************************************************************************/
7419 :
7420 : /**
7421 : \brief Set dataset style table.
7422 :
7423 : This method operate exactly as SetStyleTableDirectly() except
7424 : that it does not assume ownership of the passed table.
7425 :
7426 : This method is the same as the C function GDALDatasetSetStyleTable() and the
7427 : deprecated OGR_DS_SetStyleTable().
7428 :
7429 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7430 :
7431 : @param poStyleTable pointer to style table to set
7432 :
7433 : */
7434 :
7435 628 : void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7436 : {
7437 628 : if (m_poStyleTable)
7438 0 : delete m_poStyleTable;
7439 628 : if (poStyleTable)
7440 1 : m_poStyleTable = poStyleTable->Clone();
7441 628 : }
7442 :
7443 : /************************************************************************/
7444 : /* IsGenericSQLDialect() */
7445 : /************************************************************************/
7446 :
7447 : //! @cond Doxygen_Suppress
7448 1689 : int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7449 : {
7450 3061 : return pszDialect != nullptr &&
7451 3061 : (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7452 : }
7453 :
7454 : //! @endcond
7455 :
7456 : /************************************************************************/
7457 : /* GetLayerCount() */
7458 : /************************************************************************/
7459 :
7460 : /**
7461 : \brief Get the number of layers in this dataset.
7462 :
7463 : This method is the same as the C function GDALDatasetGetLayerCount(),
7464 : and the deprecated OGR_DS_GetLayerCount().
7465 :
7466 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7467 :
7468 : @return layer count.
7469 : */
7470 :
7471 76667 : int GDALDataset::GetLayerCount()
7472 : {
7473 76667 : return 0;
7474 : }
7475 :
7476 : /************************************************************************/
7477 : /* GetLayer() */
7478 : /************************************************************************/
7479 :
7480 : /**
7481 : \fn GDALDataset::GetLayer(int)
7482 : \brief Fetch a layer by index.
7483 :
7484 : The returned layer remains owned by the
7485 : GDALDataset and should not be deleted by the application.
7486 :
7487 : See GetLayers() for a C++ iterator version of this method.
7488 :
7489 : This method is the same as the C function GDALDatasetGetLayer() and the
7490 : deprecated OGR_DS_GetLayer().
7491 :
7492 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7493 :
7494 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7495 :
7496 : @return the layer, or NULL if iLayer is out of range or an error occurs.
7497 :
7498 : @see GetLayers()
7499 : */
7500 :
7501 0 : OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)
7502 : {
7503 0 : return nullptr;
7504 : }
7505 :
7506 : /************************************************************************/
7507 : /* IsLayerPrivate() */
7508 : /************************************************************************/
7509 :
7510 : /**
7511 : \fn GDALDataset::IsLayerPrivate(int)
7512 : \brief Returns true if the layer at the specified index is deemed a private or
7513 : system table, or an internal detail only.
7514 :
7515 : This method is the same as the C function GDALDatasetIsLayerPrivate().
7516 :
7517 : @param iLayer a layer number between 0 and GetLayerCount()-1.
7518 :
7519 : @return true if the layer is a private or system table.
7520 :
7521 : @since GDAL 3.4
7522 : */
7523 :
7524 632 : bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7525 : {
7526 632 : return false;
7527 : }
7528 :
7529 : /************************************************************************/
7530 : /* ResetReading() */
7531 : /************************************************************************/
7532 :
7533 : /**
7534 : \brief Reset feature reading to start on the first feature.
7535 :
7536 : This affects GetNextFeature().
7537 :
7538 : Depending on drivers, this may also have the side effect of calling
7539 : OGRLayer::ResetReading() on the layers of this dataset.
7540 :
7541 : This method is the same as the C function GDALDatasetResetReading().
7542 :
7543 : @since GDAL 2.2
7544 : */
7545 5 : void GDALDataset::ResetReading()
7546 : {
7547 5 : if (!m_poPrivate)
7548 0 : return;
7549 5 : m_poPrivate->nCurrentLayerIdx = 0;
7550 5 : m_poPrivate->nLayerCount = -1;
7551 5 : m_poPrivate->poCurrentLayer = nullptr;
7552 5 : m_poPrivate->nFeatureReadInLayer = 0;
7553 5 : m_poPrivate->nFeatureReadInDataset = 0;
7554 5 : m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7555 5 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7556 : }
7557 :
7558 : /************************************************************************/
7559 : /* GDALDatasetResetReading() */
7560 : /************************************************************************/
7561 :
7562 : /**
7563 : \brief Reset feature reading to start on the first feature.
7564 :
7565 : This affects GDALDatasetGetNextFeature().
7566 :
7567 : Depending on drivers, this may also have the side effect of calling
7568 : OGR_L_ResetReading() on the layers of this dataset.
7569 :
7570 : This method is the same as the C++ method GDALDataset::ResetReading()
7571 :
7572 : @param hDS dataset handle
7573 : @since GDAL 2.2
7574 : */
7575 8 : void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7576 : {
7577 8 : VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7578 :
7579 8 : return GDALDataset::FromHandle(hDS)->ResetReading();
7580 : }
7581 :
7582 : /************************************************************************/
7583 : /* GetNextFeature() */
7584 : /************************************************************************/
7585 :
7586 : /**
7587 : \brief Fetch the next available feature from this dataset.
7588 :
7589 : This method is intended for the few drivers where OGRLayer::GetNextFeature()
7590 : is not efficient, but in general OGRLayer::GetNextFeature() is a more
7591 : natural API.
7592 :
7593 : See GetFeatures() for a C++ iterator version of this method.
7594 :
7595 : The returned feature becomes the responsibility of the caller to
7596 : delete with OGRFeature::DestroyFeature().
7597 :
7598 : Depending on the driver, this method may return features from layers in a
7599 : non sequential way. This is what may happen when the
7600 : ODsCRandomLayerRead capability is declared (for example for the
7601 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7602 : advised to use GDALDataset::GetNextFeature() instead of
7603 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7604 : implementation.
7605 :
7606 : The default implementation, used by most drivers, will
7607 : however iterate over each layer, and then over each feature within this
7608 : layer.
7609 :
7610 : This method takes into account spatial and attribute filters set on layers that
7611 : will be iterated upon.
7612 :
7613 : The ResetReading() method can be used to start at the beginning again.
7614 :
7615 : Depending on drivers, this may also have the side effect of calling
7616 : OGRLayer::GetNextFeature() on the layers of this dataset.
7617 :
7618 : This method is the same as the C function GDALDatasetGetNextFeature().
7619 :
7620 : @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
7621 : layer to which the object belongs to, or NULL.
7622 : It is possible that the output of *ppoBelongingLayer
7623 : to be NULL despite the feature not being NULL.
7624 : @param pdfProgressPct a pointer to a double variable to receive the
7625 : percentage progress (in [0,1] range), or NULL.
7626 : On return, the pointed value might be negative if
7627 : determining the progress is not possible.
7628 : @param pfnProgress a progress callback to report progress (for
7629 : GetNextFeature() calls that might have a long
7630 : duration) and offer cancellation possibility, or NULL.
7631 : @param pProgressData user data provided to pfnProgress, or NULL
7632 : @return a feature, or NULL if no more features are available.
7633 : @since GDAL 2.2
7634 : @see GetFeatures()
7635 : */
7636 :
7637 47 : OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
7638 : double *pdfProgressPct,
7639 : GDALProgressFunc pfnProgress,
7640 : void *pProgressData)
7641 : {
7642 47 : if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
7643 : {
7644 2 : if (ppoBelongingLayer != nullptr)
7645 2 : *ppoBelongingLayer = nullptr;
7646 2 : if (pdfProgressPct != nullptr)
7647 1 : *pdfProgressPct = 1.0;
7648 2 : if (pfnProgress != nullptr)
7649 0 : pfnProgress(1.0, "", pProgressData);
7650 2 : return nullptr;
7651 : }
7652 :
7653 45 : if (m_poPrivate->poCurrentLayer == nullptr &&
7654 6 : (pdfProgressPct != nullptr || pfnProgress != nullptr))
7655 : {
7656 1 : if (m_poPrivate->nLayerCount < 0)
7657 : {
7658 1 : m_poPrivate->nLayerCount = GetLayerCount();
7659 : }
7660 :
7661 1 : if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
7662 : {
7663 1 : m_poPrivate->nTotalFeatures = 0;
7664 5 : for (int i = 0; i < m_poPrivate->nLayerCount; i++)
7665 : {
7666 4 : OGRLayer *poLayer = GetLayer(i);
7667 8 : if (poLayer == nullptr ||
7668 4 : !poLayer->TestCapability(OLCFastFeatureCount))
7669 : {
7670 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7671 0 : break;
7672 : }
7673 4 : GIntBig nCount = poLayer->GetFeatureCount(FALSE);
7674 4 : if (nCount < 0)
7675 : {
7676 0 : m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7677 0 : break;
7678 : }
7679 4 : m_poPrivate->nTotalFeatures += nCount;
7680 : }
7681 : }
7682 : }
7683 :
7684 : while (true)
7685 : {
7686 56 : if (m_poPrivate->poCurrentLayer == nullptr)
7687 : {
7688 36 : m_poPrivate->poCurrentLayer =
7689 18 : GetLayer(m_poPrivate->nCurrentLayerIdx);
7690 18 : if (m_poPrivate->poCurrentLayer == nullptr)
7691 : {
7692 5 : m_poPrivate->nCurrentLayerIdx = -1;
7693 5 : if (ppoBelongingLayer != nullptr)
7694 5 : *ppoBelongingLayer = nullptr;
7695 5 : if (pdfProgressPct != nullptr)
7696 1 : *pdfProgressPct = 1.0;
7697 5 : return nullptr;
7698 : }
7699 13 : m_poPrivate->poCurrentLayer->ResetReading();
7700 13 : m_poPrivate->nFeatureReadInLayer = 0;
7701 13 : if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
7702 : {
7703 0 : if (m_poPrivate->poCurrentLayer->TestCapability(
7704 0 : OLCFastFeatureCount))
7705 0 : m_poPrivate->nTotalFeaturesInLayer =
7706 0 : m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7707 : else
7708 0 : m_poPrivate->nTotalFeaturesInLayer = 0;
7709 : }
7710 : }
7711 51 : OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7712 51 : if (poFeature == nullptr)
7713 : {
7714 11 : m_poPrivate->nCurrentLayerIdx++;
7715 11 : m_poPrivate->poCurrentLayer = nullptr;
7716 11 : continue;
7717 : }
7718 :
7719 40 : m_poPrivate->nFeatureReadInLayer++;
7720 40 : m_poPrivate->nFeatureReadInDataset++;
7721 40 : if (pdfProgressPct != nullptr || pfnProgress != nullptr)
7722 : {
7723 4 : double dfPct = 0.0;
7724 4 : if (m_poPrivate->nTotalFeatures > 0)
7725 : {
7726 4 : dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7727 4 : m_poPrivate->nTotalFeatures;
7728 : }
7729 : else
7730 : {
7731 0 : dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
7732 0 : m_poPrivate->nLayerCount;
7733 0 : if (m_poPrivate->nTotalFeaturesInLayer > 0)
7734 : {
7735 0 : dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7736 0 : m_poPrivate->nTotalFeaturesInLayer /
7737 0 : m_poPrivate->nLayerCount;
7738 : }
7739 : }
7740 4 : if (pdfProgressPct)
7741 4 : *pdfProgressPct = dfPct;
7742 4 : if (pfnProgress)
7743 0 : pfnProgress(dfPct, "", nullptr);
7744 : }
7745 :
7746 40 : if (ppoBelongingLayer != nullptr)
7747 40 : *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7748 40 : return poFeature;
7749 11 : }
7750 : }
7751 :
7752 : /************************************************************************/
7753 : /* GDALDatasetGetNextFeature() */
7754 : /************************************************************************/
7755 : /**
7756 : \brief Fetch the next available feature from this dataset.
7757 :
7758 : This method is intended for the few drivers where OGR_L_GetNextFeature()
7759 : is not efficient, but in general OGR_L_GetNextFeature() is a more
7760 : natural API.
7761 :
7762 : The returned feature becomes the responsibility of the caller to
7763 : delete with OGRFeature::DestroyFeature().
7764 :
7765 : Depending on the driver, this method may return features from layers in a
7766 : non sequential way. This is what may happen when the
7767 : ODsCRandomLayerRead capability is declared (for example for the
7768 : OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7769 : advised to use GDALDataset::GetNextFeature() instead of
7770 : OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7771 : implementation.
7772 :
7773 : The default implementation, used by most drivers, will
7774 : however iterate over each layer, and then over each feature within this
7775 : layer.
7776 :
7777 : This method takes into account spatial and attribute filters set on layers that
7778 : will be iterated upon.
7779 :
7780 : The ResetReading() method can be used to start at the beginning again.
7781 :
7782 : Depending on drivers, this may also have the side effect of calling
7783 : OGRLayer::GetNextFeature() on the layers of this dataset.
7784 :
7785 : This method is the same as the C++ method GDALDataset::GetNextFeature()
7786 :
7787 : @param hDS dataset handle.
7788 : @param phBelongingLayer a pointer to a OGRLayer* variable to receive the
7789 : layer to which the object belongs to, or NULL.
7790 : It is possible that the output of *ppoBelongingLayer
7791 : to be NULL despite the feature not being NULL.
7792 : @param pdfProgressPct a pointer to a double variable to receive the
7793 : percentage progress (in [0,1] range), or NULL.
7794 : On return, the pointed value might be negative if
7795 : determining the progress is not possible.
7796 : @param pfnProgress a progress callback to report progress (for
7797 : GetNextFeature() calls that might have a long
7798 : duration) and offer cancellation possibility, or NULL
7799 : @param pProgressData user data provided to pfnProgress, or NULL
7800 : @return a feature, or NULL if no more features are available.
7801 : @since GDAL 2.2
7802 : */
7803 1833 : OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
7804 : OGRLayerH *phBelongingLayer,
7805 : double *pdfProgressPct,
7806 : GDALProgressFunc pfnProgress,
7807 : void *pProgressData)
7808 : {
7809 1833 : VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
7810 :
7811 3666 : return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
7812 : reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
7813 3666 : pfnProgress, pProgressData));
7814 : }
7815 :
7816 : /************************************************************************/
7817 : /* TestCapability() */
7818 : /************************************************************************/
7819 :
7820 : /**
7821 : \fn GDALDataset::TestCapability( const char * pszCap )
7822 : \brief Test if capability is available.
7823 :
7824 : One of the following dataset capability names can be passed into this
7825 : method, and a TRUE or FALSE value will be returned indicating whether or not
7826 : the capability is available for this object.
7827 :
7828 : <ul>
7829 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7830 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7831 : layers.<p>
7832 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7833 : datasource support CreateGeomField() just after layer creation.<p>
7834 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7835 : geometries.<p>
7836 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7837 : transactions.<p>
7838 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7839 : transactions through emulation.<p>
7840 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7841 : GetNextFeature() implementation, potentially returning features from
7842 : layers in a non sequential way.<p>
7843 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7844 : CreateFeature() on layers in a non sequential way.<p>
7845 : </ul>
7846 :
7847 : The \#define macro forms of the capability names should be used in preference
7848 : to the strings themselves to avoid misspelling.
7849 :
7850 : This method is the same as the C function GDALDatasetTestCapability() and the
7851 : deprecated OGR_DS_TestCapability().
7852 :
7853 : In GDAL 1.X, this method used to be in the OGRDataSource class.
7854 :
7855 : @param pszCap the capability to test.
7856 :
7857 : @return TRUE if capability available otherwise FALSE.
7858 : */
7859 :
7860 160 : int GDALDataset::TestCapability(CPL_UNUSED const char *pszCap)
7861 : {
7862 160 : return FALSE;
7863 : }
7864 :
7865 : /************************************************************************/
7866 : /* GDALDatasetTestCapability() */
7867 : /************************************************************************/
7868 :
7869 : /**
7870 : \brief Test if capability is available.
7871 :
7872 : One of the following dataset capability names can be passed into this
7873 : function, and a TRUE or FALSE value will be returned indicating whether or not
7874 : the capability is available for this object.
7875 :
7876 : <ul>
7877 : <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7878 : <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7879 : layers.<p>
7880 : <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7881 : datasource support CreateGeomField() just after layer creation.<p>
7882 : <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7883 : geometries.<p>
7884 : <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7885 : transactions.<p>
7886 : <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7887 : transactions through emulation.<p>
7888 : <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7889 : GetNextFeature() implementation, potentially returning features from
7890 : layers in a non sequential way.<p>
7891 : <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7892 : CreateFeature() on layers in a non sequential way.<p>
7893 : </ul>
7894 :
7895 : The \#define macro forms of the capability names should be used in preference
7896 : to the strings themselves to avoid misspelling.
7897 :
7898 : This function is the same as the C++ method GDALDataset::TestCapability()
7899 :
7900 : @since GDAL 2.0
7901 :
7902 : @param hDS the dataset handle.
7903 : @param pszCap the capability to test.
7904 :
7905 : @return TRUE if capability available otherwise FALSE.
7906 : */
7907 113 : int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
7908 :
7909 : {
7910 113 : VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
7911 113 : VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
7912 :
7913 113 : return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
7914 : }
7915 :
7916 : /************************************************************************/
7917 : /* StartTransaction() */
7918 : /************************************************************************/
7919 :
7920 : /**
7921 : \fn GDALDataset::StartTransaction(int)
7922 : \brief For datasources which support transactions, StartTransaction creates a
7923 : `transaction.
7924 :
7925 : If starting the transaction fails, will return
7926 : OGRERR_FAILURE. Datasources which do not support transactions will
7927 : always return OGRERR_UNSUPPORTED_OPERATION.
7928 :
7929 : Nested transactions are not supported.
7930 :
7931 : All changes done after the start of the transaction are definitely applied in
7932 : the datasource if CommitTransaction() is called. They may be canceled by
7933 : calling RollbackTransaction() instead.
7934 :
7935 : At the time of writing, transactions only apply on vector layers.
7936 :
7937 : Datasets that support transactions will advertise the ODsCTransactions
7938 : capability. Use of transactions at dataset level is generally preferred to
7939 : transactions at layer level, whose scope is rarely limited to the layer from
7940 : which it was started.
7941 :
7942 : In case StartTransaction() fails, neither CommitTransaction() or
7943 : RollbackTransaction() should be called.
7944 :
7945 : If an error occurs after a successful StartTransaction(), the whole transaction
7946 : may or may not be implicitly canceled, depending on drivers. (e.g. the PG
7947 : driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
7948 : an explicit call to RollbackTransaction() should be done to keep things
7949 : balanced.
7950 :
7951 : By default, when bForce is set to FALSE, only "efficient" transactions will be
7952 : attempted. Some drivers may offer an emulation of transactions, but sometimes
7953 : with significant overhead, in which case the user must explicitly allow for
7954 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
7955 : transactions should advertise the ODsCEmulatedTransactions capability (and not
7956 : ODsCTransactions).
7957 :
7958 : This function is the same as the C function GDALDatasetStartTransaction().
7959 :
7960 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
7961 : transaction
7962 : mechanism is acceptable.
7963 :
7964 : @return OGRERR_NONE on success.
7965 : @since GDAL 2.0
7966 : */
7967 :
7968 37 : OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
7969 : {
7970 37 : return OGRERR_UNSUPPORTED_OPERATION;
7971 : }
7972 :
7973 : /************************************************************************/
7974 : /* GDALDatasetStartTransaction() */
7975 : /************************************************************************/
7976 :
7977 : /**
7978 : \brief For datasources which support transactions, StartTransaction creates a
7979 : transaction.
7980 :
7981 : If starting the transaction fails, will return
7982 : OGRERR_FAILURE. Datasources which do not support transactions will
7983 : always return OGRERR_UNSUPPORTED_OPERATION.
7984 :
7985 : Nested transactions are not supported.
7986 :
7987 : All changes done after the start of the transaction are definitely applied in
7988 : the datasource if CommitTransaction() is called. They may be canceled by
7989 : calling RollbackTransaction() instead.
7990 :
7991 : At the time of writing, transactions only apply on vector layers.
7992 :
7993 : Datasets that support transactions will advertise the ODsCTransactions
7994 : capability.
7995 : Use of transactions at dataset level is generally preferred to transactions at
7996 : layer level, whose scope is rarely limited to the layer from which it was
7997 : started.
7998 :
7999 : In case StartTransaction() fails, neither CommitTransaction() or
8000 : RollbackTransaction() should be called.
8001 :
8002 : If an error occurs after a successful StartTransaction(), the whole
8003 : transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8004 : the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8005 : error, an explicit call to RollbackTransaction() should be done to keep things
8006 : balanced.
8007 :
8008 : By default, when bForce is set to FALSE, only "efficient" transactions will be
8009 : attempted. Some drivers may offer an emulation of transactions, but sometimes
8010 : with significant overhead, in which case the user must explicitly allow for
8011 : such an emulation by setting bForce to TRUE. Drivers that offer emulated
8012 : transactions should advertise the ODsCEmulatedTransactions capability (and not
8013 : ODsCTransactions).
8014 :
8015 : This function is the same as the C++ method GDALDataset::StartTransaction()
8016 :
8017 : @param hDS the dataset handle.
8018 : @param bForce can be set to TRUE if an emulation, possibly slow, of a
8019 : transaction
8020 : mechanism is acceptable.
8021 :
8022 : @return OGRERR_NONE on success.
8023 : @since GDAL 2.0
8024 : */
8025 73 : OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8026 : {
8027 73 : VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8028 : OGRERR_INVALID_HANDLE);
8029 :
8030 : #ifdef OGRAPISPY_ENABLED
8031 73 : if (bOGRAPISpyEnabled)
8032 2 : OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8033 : #endif
8034 :
8035 73 : return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8036 : }
8037 :
8038 : /************************************************************************/
8039 : /* CommitTransaction() */
8040 : /************************************************************************/
8041 :
8042 : /**
8043 : \brief For datasources which support transactions, CommitTransaction commits a
8044 : transaction.
8045 :
8046 : If no transaction is active, or the commit fails, will return
8047 : OGRERR_FAILURE. Datasources which do not support transactions will
8048 : always return OGRERR_UNSUPPORTED_OPERATION.
8049 :
8050 : Depending on drivers, this may or may not abort layer sequential readings that
8051 : are active.
8052 :
8053 : This function is the same as the C function GDALDatasetCommitTransaction().
8054 :
8055 : @return OGRERR_NONE on success.
8056 : @since GDAL 2.0
8057 : */
8058 37 : OGRErr GDALDataset::CommitTransaction()
8059 : {
8060 37 : return OGRERR_UNSUPPORTED_OPERATION;
8061 : }
8062 :
8063 : /************************************************************************/
8064 : /* GDALDatasetCommitTransaction() */
8065 : /************************************************************************/
8066 :
8067 : /**
8068 : \brief For datasources which support transactions, CommitTransaction commits a
8069 : transaction.
8070 :
8071 : If no transaction is active, or the commit fails, will return
8072 : OGRERR_FAILURE. Datasources which do not support transactions will
8073 : always return OGRERR_UNSUPPORTED_OPERATION.
8074 :
8075 : Depending on drivers, this may or may not abort layer sequential readings that
8076 : are active.
8077 :
8078 : This function is the same as the C++ method GDALDataset::CommitTransaction()
8079 :
8080 : @return OGRERR_NONE on success.
8081 : @since GDAL 2.0
8082 : */
8083 43 : OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8084 : {
8085 43 : VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8086 : OGRERR_INVALID_HANDLE);
8087 :
8088 : #ifdef OGRAPISPY_ENABLED
8089 43 : if (bOGRAPISpyEnabled)
8090 2 : OGRAPISpy_Dataset_CommitTransaction(hDS);
8091 : #endif
8092 :
8093 43 : return GDALDataset::FromHandle(hDS)->CommitTransaction();
8094 : }
8095 :
8096 : /************************************************************************/
8097 : /* RollbackTransaction() */
8098 : /************************************************************************/
8099 :
8100 : /**
8101 : \brief For datasources which support transactions, RollbackTransaction will
8102 : roll back a datasource to its state before the start of the current
8103 : transaction.
8104 : If no transaction is active, or the rollback fails, will return
8105 : OGRERR_FAILURE. Datasources which do not support transactions will
8106 : always return OGRERR_UNSUPPORTED_OPERATION.
8107 :
8108 : This function is the same as the C function GDALDatasetRollbackTransaction().
8109 :
8110 : @return OGRERR_NONE on success.
8111 : @since GDAL 2.0
8112 : */
8113 2 : OGRErr GDALDataset::RollbackTransaction()
8114 : {
8115 2 : return OGRERR_UNSUPPORTED_OPERATION;
8116 : }
8117 :
8118 : /************************************************************************/
8119 : /* GDALDatasetRollbackTransaction() */
8120 : /************************************************************************/
8121 :
8122 : /**
8123 : \brief For datasources which support transactions, RollbackTransaction will
8124 : roll back a datasource to its state before the start of the current
8125 : transaction.
8126 : If no transaction is active, or the rollback fails, will return
8127 : OGRERR_FAILURE. Datasources which do not support transactions will
8128 : always return OGRERR_UNSUPPORTED_OPERATION.
8129 :
8130 : This function is the same as the C++ method GDALDataset::RollbackTransaction().
8131 :
8132 : @return OGRERR_NONE on success.
8133 : @since GDAL 2.0
8134 : */
8135 31 : OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8136 : {
8137 31 : VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8138 : OGRERR_INVALID_HANDLE);
8139 :
8140 : #ifdef OGRAPISPY_ENABLED
8141 31 : if (bOGRAPISpyEnabled)
8142 2 : OGRAPISpy_Dataset_RollbackTransaction(hDS);
8143 : #endif
8144 :
8145 31 : return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8146 : }
8147 :
8148 : //! @cond Doxygen_Suppress
8149 :
8150 : /************************************************************************/
8151 : /* ShareLockWithParentDataset() */
8152 : /************************************************************************/
8153 :
8154 : /* To be used typically by the GTiff driver to link overview datasets */
8155 : /* with their main dataset, so that they share the same lock */
8156 : /* Cf https://github.com/OSGeo/gdal/issues/1488 */
8157 : /* The parent dataset should remain alive while the this dataset is alive */
8158 :
8159 2041 : void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8160 : {
8161 2041 : if (m_poPrivate != nullptr)
8162 : {
8163 2041 : m_poPrivate->poParentDataset = poParentDataset;
8164 : }
8165 2041 : }
8166 :
8167 : /************************************************************************/
8168 : /* SetQueryLoggerFunc() */
8169 : /************************************************************************/
8170 :
8171 0 : bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8172 : CPL_UNUSED void *context)
8173 : {
8174 0 : return false;
8175 : }
8176 :
8177 : /************************************************************************/
8178 : /* EnterReadWrite() */
8179 : /************************************************************************/
8180 :
8181 6481890 : int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8182 : {
8183 6481890 : if (m_poPrivate == nullptr)
8184 0 : return FALSE;
8185 :
8186 6481890 : if (m_poPrivate->poParentDataset)
8187 38274 : return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8188 :
8189 6443610 : if (eAccess == GA_Update)
8190 : {
8191 1505930 : if (m_poPrivate->eStateReadWriteMutex ==
8192 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8193 : {
8194 : // In case dead-lock would occur, which is not impossible,
8195 : // this can be used to prevent it, but at the risk of other
8196 : // issues.
8197 5854 : if (CPLTestBool(
8198 : CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8199 : {
8200 5854 : m_poPrivate->eStateReadWriteMutex =
8201 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8202 : }
8203 : else
8204 : {
8205 0 : m_poPrivate->eStateReadWriteMutex =
8206 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8207 : }
8208 : }
8209 1505930 : if (m_poPrivate->eStateReadWriteMutex ==
8210 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8211 : {
8212 : // There should be no race related to creating this mutex since
8213 : // it should be first created through IWriteBlock() / IRasterIO()
8214 : // and then GDALRasterBlock might call it from another thread.
8215 : #ifdef DEBUG_VERBOSE
8216 : CPLDebug("GDAL",
8217 : "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8218 : CPLGetPID(), GetDescription());
8219 : #endif
8220 991667 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8221 :
8222 : const int nCountMutex =
8223 992254 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8224 992003 : if (nCountMutex == 0 && eRWFlag == GF_Read)
8225 : {
8226 313313 : CPLReleaseMutex(m_poPrivate->hMutex);
8227 762767 : for (int i = 0; i < nBands; i++)
8228 : {
8229 449454 : auto blockCache = papoBands[i]->poBandBlockCache;
8230 449454 : if (blockCache)
8231 414615 : blockCache->WaitCompletionPendingTasks();
8232 : }
8233 313313 : CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8234 : }
8235 :
8236 992032 : return TRUE;
8237 : }
8238 : }
8239 5451950 : return FALSE;
8240 : }
8241 :
8242 : /************************************************************************/
8243 : /* LeaveReadWrite() */
8244 : /************************************************************************/
8245 :
8246 1019000 : void GDALDataset::LeaveReadWrite()
8247 : {
8248 1019000 : if (m_poPrivate)
8249 : {
8250 1018990 : if (m_poPrivate->poParentDataset)
8251 : {
8252 26861 : m_poPrivate->poParentDataset->LeaveReadWrite();
8253 26861 : return;
8254 : }
8255 :
8256 992133 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8257 991784 : CPLReleaseMutex(m_poPrivate->hMutex);
8258 : #ifdef DEBUG_VERBOSE
8259 : CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8260 : CPLGetPID(), GetDescription());
8261 : #endif
8262 : }
8263 : }
8264 :
8265 : /************************************************************************/
8266 : /* InitRWLock() */
8267 : /************************************************************************/
8268 :
8269 3625470 : void GDALDataset::InitRWLock()
8270 : {
8271 3625470 : if (m_poPrivate)
8272 : {
8273 3625470 : if (m_poPrivate->poParentDataset)
8274 : {
8275 7024 : m_poPrivate->poParentDataset->InitRWLock();
8276 7024 : return;
8277 : }
8278 :
8279 3618450 : if (m_poPrivate->eStateReadWriteMutex ==
8280 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8281 : {
8282 1 : if (EnterReadWrite(GF_Write))
8283 1 : LeaveReadWrite();
8284 : }
8285 : }
8286 : }
8287 :
8288 : /************************************************************************/
8289 : /* DisableReadWriteMutex() */
8290 : /************************************************************************/
8291 :
8292 : // The mutex logic is broken in multi-threaded situations, for example
8293 : // with 2 WarpedVRT datasets being read at the same time. In that
8294 : // particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8295 : // to disable it.
8296 15291 : void GDALDataset::DisableReadWriteMutex()
8297 : {
8298 15291 : if (m_poPrivate)
8299 : {
8300 15289 : if (m_poPrivate->poParentDataset)
8301 : {
8302 0 : m_poPrivate->poParentDataset->DisableReadWriteMutex();
8303 0 : return;
8304 : }
8305 :
8306 15289 : m_poPrivate->eStateReadWriteMutex =
8307 : GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8308 : }
8309 : }
8310 :
8311 : /************************************************************************/
8312 : /* TemporarilyDropReadWriteLock() */
8313 : /************************************************************************/
8314 :
8315 2989770 : void GDALDataset::TemporarilyDropReadWriteLock()
8316 : {
8317 2989770 : if (m_poPrivate == nullptr)
8318 0 : return;
8319 :
8320 2989770 : if (m_poPrivate->poParentDataset)
8321 : {
8322 22983 : m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8323 22983 : return;
8324 : }
8325 :
8326 2966790 : if (m_poPrivate->hMutex)
8327 : {
8328 : #ifdef DEBUG_VERBOSE
8329 : CPLDebug("GDAL",
8330 : "[Thread " CPL_FRMT_GIB "] "
8331 : "Temporarily drop RW mutex for %s",
8332 : CPLGetPID(), GetDescription());
8333 : #endif
8334 290429 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8335 : const int nCount =
8336 290429 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8337 : #ifdef DEBUG_EXTRA
8338 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8339 : #endif
8340 883745 : for (int i = 0; i < nCount + 1; i++)
8341 : {
8342 : // The mutex is recursive
8343 : // coverity[double_unlock]
8344 593316 : CPLReleaseMutex(m_poPrivate->hMutex);
8345 : }
8346 : }
8347 : }
8348 :
8349 : /************************************************************************/
8350 : /* ReacquireReadWriteLock() */
8351 : /************************************************************************/
8352 :
8353 2989770 : void GDALDataset::ReacquireReadWriteLock()
8354 : {
8355 2989770 : if (m_poPrivate == nullptr)
8356 0 : return;
8357 :
8358 2989770 : if (m_poPrivate->poParentDataset)
8359 : {
8360 22983 : m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8361 22983 : return;
8362 : }
8363 :
8364 2966790 : if (m_poPrivate->hMutex)
8365 : {
8366 : #ifdef DEBUG_VERBOSE
8367 : CPLDebug("GDAL",
8368 : "[Thread " CPL_FRMT_GIB "] "
8369 : "Reacquire temporarily dropped RW mutex for %s",
8370 : CPLGetPID(), GetDescription());
8371 : #endif
8372 290431 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8373 : const int nCount =
8374 290431 : m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8375 : #ifdef DEBUG_EXTRA
8376 : CPLAssert(nCount ==
8377 : m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8378 : #endif
8379 290431 : if (nCount == 0)
8380 11502 : CPLReleaseMutex(m_poPrivate->hMutex);
8381 314389 : for (int i = 0; i < nCount - 1; i++)
8382 : {
8383 : // The mutex is recursive
8384 : // coverity[double_lock]
8385 23958 : CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8386 : }
8387 : }
8388 : }
8389 :
8390 : /************************************************************************/
8391 : /* AcquireMutex() */
8392 : /************************************************************************/
8393 :
8394 192 : int GDALDataset::AcquireMutex()
8395 : {
8396 192 : if (m_poPrivate == nullptr)
8397 0 : return 0;
8398 192 : if (m_poPrivate->poParentDataset)
8399 : {
8400 0 : return m_poPrivate->poParentDataset->AcquireMutex();
8401 : }
8402 :
8403 192 : return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8404 : }
8405 :
8406 : /************************************************************************/
8407 : /* ReleaseMutex() */
8408 : /************************************************************************/
8409 :
8410 192 : void GDALDataset::ReleaseMutex()
8411 : {
8412 192 : if (m_poPrivate)
8413 : {
8414 192 : if (m_poPrivate->poParentDataset)
8415 : {
8416 0 : m_poPrivate->poParentDataset->ReleaseMutex();
8417 0 : return;
8418 : }
8419 :
8420 192 : CPLReleaseMutex(m_poPrivate->hMutex);
8421 : }
8422 : }
8423 :
8424 : //! @endcond
8425 :
8426 : /************************************************************************/
8427 : /* GDALDataset::Features::Iterator::Private */
8428 : /************************************************************************/
8429 :
8430 : struct GDALDataset::Features::Iterator::Private
8431 : {
8432 : GDALDataset::FeatureLayerPair m_oPair{};
8433 : GDALDataset *m_poDS = nullptr;
8434 : bool m_bEOF = true;
8435 : };
8436 :
8437 4 : GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8438 4 : : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8439 : {
8440 4 : m_poPrivate->m_poDS = poDS;
8441 4 : if (bStart)
8442 : {
8443 2 : poDS->ResetReading();
8444 4 : m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8445 2 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8446 2 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8447 : }
8448 4 : }
8449 :
8450 : GDALDataset::Features::Iterator::~Iterator() = default;
8451 :
8452 : const GDALDataset::FeatureLayerPair &
8453 20 : GDALDataset::Features::Iterator::operator*() const
8454 : {
8455 20 : return m_poPrivate->m_oPair;
8456 : }
8457 :
8458 20 : GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8459 : {
8460 40 : m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8461 20 : &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8462 20 : m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8463 20 : return *this;
8464 : }
8465 :
8466 22 : bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8467 : {
8468 22 : return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8469 : }
8470 :
8471 : /************************************************************************/
8472 : /* GetFeatures() */
8473 : /************************************************************************/
8474 :
8475 : /** Function that return an iterable object over features in the dataset
8476 : * layer.
8477 : *
8478 : * This is a C++ iterator friendly version of GetNextFeature().
8479 : *
8480 : * Using this iterator for standard range-based loops is safe, but
8481 : * due to implementation limitations, you shouldn't try to access
8482 : * (dereference) more than one iterator step at a time, since the
8483 : * FeatureLayerPair reference which is returned is reused.
8484 : *
8485 : * Typical use is:
8486 : * \code{.cpp}
8487 : * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8488 : * {
8489 : * std::cout << "Feature of layer " <<
8490 : * oFeatureLayerPair.layer->GetName() << std::endl;
8491 : * oFeatureLayerPair.feature->DumpReadable();
8492 : * }
8493 : * \endcode
8494 : *
8495 : * @see GetNextFeature()
8496 : *
8497 : * @since GDAL 2.3
8498 : */
8499 2 : GDALDataset::Features GDALDataset::GetFeatures()
8500 : {
8501 2 : return Features(this);
8502 : }
8503 :
8504 : /************************************************************************/
8505 : /* begin() */
8506 : /************************************************************************/
8507 :
8508 : /**
8509 : \brief Return beginning of feature iterator.
8510 :
8511 : @since GDAL 2.3
8512 : */
8513 :
8514 2 : const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8515 : {
8516 2 : return {m_poSelf, true};
8517 : }
8518 :
8519 : /************************************************************************/
8520 : /* end() */
8521 : /************************************************************************/
8522 :
8523 : /**
8524 : \brief Return end of feature iterator.
8525 :
8526 : @since GDAL 2.3
8527 : */
8528 :
8529 2 : const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8530 : {
8531 2 : return {m_poSelf, false};
8532 : }
8533 :
8534 : /************************************************************************/
8535 : /* GDALDataset::Layers::Iterator::Private */
8536 : /************************************************************************/
8537 :
8538 : struct GDALDataset::Layers::Iterator::Private
8539 : {
8540 : OGRLayer *m_poLayer = nullptr;
8541 : int m_iCurLayer = 0;
8542 : int m_nLayerCount = 0;
8543 : GDALDataset *m_poDS = nullptr;
8544 : };
8545 :
8546 2 : GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8547 : {
8548 2 : }
8549 :
8550 : // False positive of cppcheck 1.72
8551 : // cppcheck-suppress uninitMemberVar
8552 9 : GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8553 9 : : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8554 : {
8555 9 : }
8556 :
8557 5 : GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
8558 5 : : m_poPrivate(std::move(oOther.m_poPrivate))
8559 : {
8560 5 : }
8561 :
8562 16 : GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8563 16 : : m_poPrivate(new Private())
8564 : {
8565 16 : m_poPrivate->m_poDS = poDS;
8566 16 : m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
8567 16 : if (bStart)
8568 : {
8569 9 : if (m_poPrivate->m_nLayerCount)
8570 8 : m_poPrivate->m_poLayer = poDS->GetLayer(0);
8571 : }
8572 : else
8573 : {
8574 7 : m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
8575 : }
8576 16 : }
8577 :
8578 : GDALDataset::Layers::Iterator::~Iterator() = default;
8579 :
8580 : // False positive of cppcheck 1.72
8581 : // cppcheck-suppress operatorEqVarError
8582 : GDALDataset::Layers::Iterator &
8583 1 : GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
8584 : {
8585 1 : *m_poPrivate = *oOther.m_poPrivate;
8586 1 : return *this;
8587 : }
8588 :
8589 1 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
8590 : GDALDataset::Layers::Iterator &&oOther) noexcept
8591 : {
8592 1 : m_poPrivate = std::move(oOther.m_poPrivate);
8593 1 : return *this;
8594 : }
8595 :
8596 11 : OGRLayer *GDALDataset::Layers::Iterator::operator*() const
8597 : {
8598 11 : return m_poPrivate->m_poLayer;
8599 : }
8600 :
8601 11 : GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
8602 : {
8603 11 : m_poPrivate->m_iCurLayer++;
8604 11 : if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
8605 : {
8606 7 : m_poPrivate->m_poLayer =
8607 7 : m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
8608 : }
8609 : else
8610 : {
8611 4 : m_poPrivate->m_poLayer = nullptr;
8612 : }
8613 11 : return *this;
8614 : }
8615 :
8616 2 : GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
8617 : {
8618 2 : GDALDataset::Layers::Iterator temp = *this;
8619 2 : ++(*this);
8620 2 : return temp;
8621 : }
8622 :
8623 12 : bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
8624 : {
8625 12 : return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
8626 : }
8627 :
8628 : /************************************************************************/
8629 : /* GetLayers() */
8630 : /************************************************************************/
8631 :
8632 : /** Function that returns an iterable object over layers in the dataset.
8633 : *
8634 : * This is a C++ iterator friendly version of GetLayer().
8635 : *
8636 : * Typical use is:
8637 : * \code{.cpp}
8638 : * for( auto&& poLayer: poDS->GetLayers() )
8639 : * {
8640 : * std::cout << "Layer << poLayer->GetName() << std::endl;
8641 : * }
8642 : * \endcode
8643 : *
8644 : * @see GetLayer()
8645 : *
8646 : * @since GDAL 2.3
8647 : */
8648 12 : GDALDataset::Layers GDALDataset::GetLayers()
8649 : {
8650 12 : return Layers(this);
8651 : }
8652 :
8653 : /************************************************************************/
8654 : /* begin() */
8655 : /************************************************************************/
8656 :
8657 : /**
8658 : \brief Return beginning of layer iterator.
8659 :
8660 : @since GDAL 2.3
8661 : */
8662 :
8663 9 : GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
8664 : {
8665 9 : return {m_poSelf, true};
8666 : }
8667 :
8668 : /************************************************************************/
8669 : /* end() */
8670 : /************************************************************************/
8671 :
8672 : /**
8673 : \brief Return end of layer iterator.
8674 :
8675 : @since GDAL 2.3
8676 : */
8677 :
8678 7 : GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
8679 : {
8680 7 : return {m_poSelf, false};
8681 : }
8682 :
8683 : /************************************************************************/
8684 : /* size() */
8685 : /************************************************************************/
8686 :
8687 : /**
8688 : \brief Get the number of layers in this dataset.
8689 :
8690 : @return layer count.
8691 :
8692 : @since GDAL 2.3
8693 : */
8694 :
8695 1 : size_t GDALDataset::Layers::size() const
8696 : {
8697 1 : return static_cast<size_t>(m_poSelf->GetLayerCount());
8698 : }
8699 :
8700 : /************************************************************************/
8701 : /* operator[]() */
8702 : /************************************************************************/
8703 : /**
8704 : \brief Fetch a layer by index.
8705 :
8706 : The returned layer remains owned by the
8707 : GDALDataset and should not be deleted by the application.
8708 :
8709 : @param iLayer a layer number between 0 and size()-1.
8710 :
8711 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8712 :
8713 : @since GDAL 2.3
8714 : */
8715 :
8716 9 : OGRLayer *GDALDataset::Layers::operator[](int iLayer)
8717 : {
8718 9 : return m_poSelf->GetLayer(iLayer);
8719 : }
8720 :
8721 : /************************************************************************/
8722 : /* operator[]() */
8723 : /************************************************************************/
8724 : /**
8725 : \brief Fetch a layer by index.
8726 :
8727 : The returned layer remains owned by the
8728 : GDALDataset and should not be deleted by the application.
8729 :
8730 : @param iLayer a layer number between 0 and size()-1.
8731 :
8732 : @return the layer, or nullptr if iLayer is out of range or an error occurs.
8733 :
8734 : @since GDAL 2.3
8735 : */
8736 :
8737 1 : OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
8738 : {
8739 1 : return m_poSelf->GetLayer(static_cast<int>(iLayer));
8740 : }
8741 :
8742 : /************************************************************************/
8743 : /* operator[]() */
8744 : /************************************************************************/
8745 : /**
8746 : \brief Fetch a layer by name.
8747 :
8748 : The returned layer remains owned by the
8749 : GDALDataset and should not be deleted by the application.
8750 :
8751 : @param pszLayerName layer name
8752 :
8753 : @return the layer, or nullptr if pszLayerName does not match with a layer
8754 :
8755 : @since GDAL 2.3
8756 : */
8757 :
8758 1 : OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
8759 : {
8760 1 : return m_poSelf->GetLayerByName(pszLayerName);
8761 : }
8762 :
8763 : /************************************************************************/
8764 : /* GDALDataset::Bands::Iterator::Private */
8765 : /************************************************************************/
8766 :
8767 : struct GDALDataset::Bands::Iterator::Private
8768 : {
8769 : GDALRasterBand *m_poBand = nullptr;
8770 : int m_iCurBand = 0;
8771 : int m_nBandCount = 0;
8772 : GDALDataset *m_poDS = nullptr;
8773 : };
8774 :
8775 2 : GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8776 2 : : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
8777 : {
8778 2 : m_poPrivate->m_poDS = poDS;
8779 2 : m_poPrivate->m_nBandCount = poDS->GetRasterCount();
8780 2 : if (bStart)
8781 : {
8782 1 : if (m_poPrivate->m_nBandCount)
8783 1 : m_poPrivate->m_poBand = poDS->GetRasterBand(1);
8784 : }
8785 : else
8786 : {
8787 1 : m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
8788 : }
8789 2 : }
8790 :
8791 : GDALDataset::Bands::Iterator::~Iterator() = default;
8792 :
8793 3 : GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
8794 : {
8795 3 : return m_poPrivate->m_poBand;
8796 : }
8797 :
8798 3 : GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
8799 : {
8800 3 : m_poPrivate->m_iCurBand++;
8801 3 : if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
8802 : {
8803 2 : m_poPrivate->m_poBand =
8804 2 : m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
8805 : }
8806 : else
8807 : {
8808 1 : m_poPrivate->m_poBand = nullptr;
8809 : }
8810 3 : return *this;
8811 : }
8812 :
8813 4 : bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
8814 : {
8815 4 : return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
8816 : }
8817 :
8818 : /************************************************************************/
8819 : /* GetBands() */
8820 : /************************************************************************/
8821 :
8822 : /** Function that returns an iterable object over GDALRasterBand in the dataset.
8823 : *
8824 : * This is a C++ iterator friendly version of GetRasterBand().
8825 : *
8826 : * Typical use is:
8827 : * \code{.cpp}
8828 : * for( auto&& poBand: poDS->GetBands() )
8829 : * {
8830 : * std::cout << "Band << poBand->GetDescription() << std::endl;
8831 : * }
8832 : * \endcode
8833 : *
8834 : * @see GetRasterBand()
8835 : *
8836 : * @since GDAL 2.3
8837 : */
8838 5 : GDALDataset::Bands GDALDataset::GetBands()
8839 : {
8840 5 : return Bands(this);
8841 : }
8842 :
8843 : /************************************************************************/
8844 : /* begin() */
8845 : /************************************************************************/
8846 :
8847 : /**
8848 : \brief Return beginning of band iterator.
8849 :
8850 : @since GDAL 2.3
8851 : */
8852 :
8853 1 : const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
8854 : {
8855 1 : return {m_poSelf, true};
8856 : }
8857 :
8858 : /************************************************************************/
8859 : /* end() */
8860 : /************************************************************************/
8861 :
8862 : /**
8863 : \brief Return end of band iterator.
8864 :
8865 : @since GDAL 2.3
8866 : */
8867 :
8868 1 : const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
8869 : {
8870 1 : return {m_poSelf, false};
8871 : }
8872 :
8873 : /************************************************************************/
8874 : /* size() */
8875 : /************************************************************************/
8876 :
8877 : /**
8878 : \brief Get the number of raster bands in this dataset.
8879 :
8880 : @return raster band count.
8881 :
8882 : @since GDAL 2.3
8883 : */
8884 :
8885 2 : size_t GDALDataset::Bands::size() const
8886 : {
8887 2 : return static_cast<size_t>(m_poSelf->GetRasterCount());
8888 : }
8889 :
8890 : /************************************************************************/
8891 : /* operator[]() */
8892 : /************************************************************************/
8893 : /**
8894 : \brief Fetch a raster band by index.
8895 :
8896 : The returned band remains owned by the
8897 : GDALDataset and should not be deleted by the application.
8898 :
8899 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
8900 : consistent with the conventions of C/C++, i.e. starting at 0.
8901 :
8902 : @param iBand a band index between 0 and size()-1.
8903 :
8904 : @return the band, or nullptr if iBand is out of range or an error occurs.
8905 :
8906 : @since GDAL 2.3
8907 : */
8908 :
8909 1 : GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
8910 : {
8911 1 : return m_poSelf->GetRasterBand(1 + iBand);
8912 : }
8913 :
8914 : /************************************************************************/
8915 : /* operator[]() */
8916 : /************************************************************************/
8917 :
8918 : /**
8919 : \brief Fetch a raster band by index.
8920 :
8921 : The returned band remains owned by the
8922 : GDALDataset and should not be deleted by the application.
8923 :
8924 : @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
8925 : consistent with the conventions of C/C++, i.e. starting at 0.
8926 :
8927 : @param iBand a band index between 0 and size()-1.
8928 :
8929 : @return the band, or nullptr if iBand is out of range or an error occurs.
8930 :
8931 : @since GDAL 2.3
8932 : */
8933 :
8934 1 : GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
8935 : {
8936 1 : return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
8937 : }
8938 :
8939 : /************************************************************************/
8940 : /* GetRootGroup() */
8941 : /************************************************************************/
8942 :
8943 : /**
8944 : \brief Return the root GDALGroup of this dataset.
8945 :
8946 : Only valid for multidimensional datasets.
8947 :
8948 : This is the same as the C function GDALDatasetGetRootGroup().
8949 :
8950 : @since GDAL 3.1
8951 : */
8952 :
8953 2441 : std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
8954 : {
8955 2441 : return nullptr;
8956 : }
8957 :
8958 : /************************************************************************/
8959 : /* GetRawBinaryLayout() */
8960 : /************************************************************************/
8961 :
8962 : //! @cond Doxygen_Suppress
8963 : /**
8964 : \brief Return the layout of a dataset that can be considered as a raw binary
8965 : format.
8966 :
8967 : @param sLayout Structure that will be set if the dataset is a raw binary one.
8968 : @return true if the dataset is a raw binary one.
8969 : @since GDAL 3.1
8970 : */
8971 :
8972 0 : bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
8973 : {
8974 0 : CPL_IGNORE_RET_VAL(sLayout);
8975 0 : return false;
8976 : }
8977 :
8978 : //! @endcond
8979 :
8980 : /************************************************************************/
8981 : /* ClearStatistics() */
8982 : /************************************************************************/
8983 :
8984 : /**
8985 : \brief Clear statistics
8986 :
8987 : Only implemented for now in PAM supported datasets
8988 :
8989 : This is the same as the C function GDALDatasetClearStatistics().
8990 :
8991 : @since GDAL 3.2
8992 : */
8993 :
8994 4 : void GDALDataset::ClearStatistics()
8995 : {
8996 8 : auto poRootGroup = GetRootGroup();
8997 4 : if (poRootGroup)
8998 1 : poRootGroup->ClearStatistics();
8999 4 : }
9000 :
9001 : /************************************************************************/
9002 : /* GDALDatasetClearStatistics() */
9003 : /************************************************************************/
9004 :
9005 : /**
9006 : \brief Clear statistics
9007 :
9008 : This is the same as the C++ method GDALDataset::ClearStatistics().
9009 :
9010 : @since GDAL 3.2
9011 : */
9012 :
9013 2 : void GDALDatasetClearStatistics(GDALDatasetH hDS)
9014 : {
9015 2 : VALIDATE_POINTER0(hDS, __func__);
9016 2 : GDALDataset::FromHandle(hDS)->ClearStatistics();
9017 : }
9018 :
9019 : /************************************************************************/
9020 : /* GetFieldDomainNames() */
9021 : /************************************************************************/
9022 :
9023 : /** Returns a list of the names of all field domains stored in the dataset.
9024 : *
9025 : * @note The default implementation assumes that drivers fully populate
9026 : * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9027 : * then a specialized implementation of GetFieldDomainNames() must be
9028 : * implemented.
9029 : *
9030 : * @param papszOptions Driver specific options determining how attributes
9031 : * should be retrieved. Pass nullptr for default behavior.
9032 : *
9033 : * @return list of field domain names
9034 : * @since GDAL 3.5
9035 : */
9036 : std::vector<std::string>
9037 30 : GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9038 : {
9039 :
9040 30 : std::vector<std::string> names;
9041 30 : names.reserve(m_oMapFieldDomains.size());
9042 42 : for (const auto &it : m_oMapFieldDomains)
9043 : {
9044 12 : names.emplace_back(it.first);
9045 : }
9046 30 : return names;
9047 : }
9048 :
9049 : /************************************************************************/
9050 : /* GDALDatasetGetFieldDomainNames() */
9051 : /************************************************************************/
9052 :
9053 : /** Returns a list of the names of all field domains stored in the dataset.
9054 : *
9055 : * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9056 : *
9057 : * @param hDS Dataset handle.
9058 : * @param papszOptions Driver specific options determining how attributes
9059 : * should be retrieved. Pass nullptr for default behavior.
9060 : *
9061 : * @return list of field domain names, to be freed with CSLDestroy()
9062 : * @since GDAL 3.5
9063 : */
9064 33 : char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9065 : CSLConstList papszOptions)
9066 : {
9067 33 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9068 : auto names =
9069 66 : GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9070 66 : CPLStringList res;
9071 141 : for (const auto &name : names)
9072 : {
9073 108 : res.AddString(name.c_str());
9074 : }
9075 33 : return res.StealList();
9076 : }
9077 :
9078 : /************************************************************************/
9079 : /* GetFieldDomain() */
9080 : /************************************************************************/
9081 :
9082 : /** Get a field domain from its name.
9083 : *
9084 : * @return the field domain, or nullptr if not found.
9085 : * @since GDAL 3.3
9086 : */
9087 291 : const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9088 : {
9089 291 : const auto iter = m_oMapFieldDomains.find(name);
9090 291 : if (iter == m_oMapFieldDomains.end())
9091 126 : return nullptr;
9092 165 : return iter->second.get();
9093 : }
9094 :
9095 : /************************************************************************/
9096 : /* GDALDatasetGetFieldDomain() */
9097 : /************************************************************************/
9098 :
9099 : /** Get a field domain from its name.
9100 : *
9101 : * This is the same as the C++ method GDALDataset::GetFieldDomain().
9102 : *
9103 : * @param hDS Dataset handle.
9104 : * @param pszName Name of field domain.
9105 : * @return the field domain (ownership remains to the dataset), or nullptr if
9106 : * not found.
9107 : * @since GDAL 3.3
9108 : */
9109 117 : OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9110 : {
9111 117 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9112 117 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9113 117 : return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9114 117 : GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9115 : }
9116 :
9117 : /************************************************************************/
9118 : /* AddFieldDomain() */
9119 : /************************************************************************/
9120 :
9121 : /** Add a field domain to the dataset.
9122 : *
9123 : * Only a few drivers will support this operation, and some of them might only
9124 : * support it only for some types of field domains.
9125 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9126 : * support this operation. A dataset having at least some support for this
9127 : * operation should report the ODsCAddFieldDomain dataset capability.
9128 : *
9129 : * Anticipated failures will not be emitted through the CPLError()
9130 : * infrastructure, but will be reported in the failureReason output parameter.
9131 : *
9132 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9133 : * default implementation of GetFieldDomainNames() to work correctly, or
9134 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9135 : * implemented.
9136 : *
9137 : * @param domain The domain definition.
9138 : * @param failureReason Output parameter. Will contain an error message if
9139 : * an error occurs.
9140 : * @return true in case of success.
9141 : * @since GDAL 3.3
9142 : */
9143 0 : bool GDALDataset::AddFieldDomain(
9144 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9145 : std::string &failureReason)
9146 : {
9147 0 : failureReason = "AddFieldDomain not supported by this driver";
9148 0 : return false;
9149 : }
9150 :
9151 : /************************************************************************/
9152 : /* GDALDatasetAddFieldDomain() */
9153 : /************************************************************************/
9154 :
9155 : /** Add a field domain to the dataset.
9156 : *
9157 : * Only a few drivers will support this operation, and some of them might only
9158 : * support it only for some types of field domains.
9159 : * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9160 : * support this operation. A dataset having at least some support for this
9161 : * operation should report the ODsCAddFieldDomain dataset capability.
9162 : *
9163 : * Anticipated failures will not be emitted through the CPLError()
9164 : * infrastructure, but will be reported in the ppszFailureReason output
9165 : * parameter.
9166 : *
9167 : * @param hDS Dataset handle.
9168 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9169 : * the passed object is copied.
9170 : * @param ppszFailureReason Output parameter. Will contain an error message if
9171 : * an error occurs (*ppszFailureReason to be freed
9172 : * with CPLFree). May be NULL.
9173 : * @return true in case of success.
9174 : * @since GDAL 3.3
9175 : */
9176 35 : bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9177 : char **ppszFailureReason)
9178 : {
9179 35 : VALIDATE_POINTER1(hDS, __func__, false);
9180 35 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9181 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9182 70 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9183 35 : if (poDomain == nullptr)
9184 0 : return false;
9185 35 : std::string failureReason;
9186 70 : const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9187 35 : std::move(poDomain), failureReason);
9188 35 : if (ppszFailureReason)
9189 : {
9190 0 : *ppszFailureReason =
9191 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9192 : }
9193 35 : return bRet;
9194 : }
9195 :
9196 : /************************************************************************/
9197 : /* DeleteFieldDomain() */
9198 : /************************************************************************/
9199 :
9200 : /** Removes a field domain from the dataset.
9201 : *
9202 : * Only a few drivers will support this operation.
9203 : *
9204 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9205 : * support this operation. A dataset having at least some support for this
9206 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9207 : *
9208 : * Anticipated failures will not be emitted through the CPLError()
9209 : * infrastructure, but will be reported in the failureReason output parameter.
9210 : *
9211 : * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9212 : * default implementation of GetFieldDomainNames() to work correctly, or
9213 : * alternatively a specialized implementation of GetFieldDomainNames() should be
9214 : * implemented.
9215 : *
9216 : * @param name The domain name.
9217 : * @param failureReason Output parameter. Will contain an error message if
9218 : * an error occurs.
9219 : * @return true in case of success.
9220 : * @since GDAL 3.5
9221 : */
9222 0 : bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
9223 : std::string &failureReason)
9224 : {
9225 0 : failureReason = "DeleteFieldDomain not supported by this driver";
9226 0 : return false;
9227 : }
9228 :
9229 : /************************************************************************/
9230 : /* GDALDatasetDeleteFieldDomain() */
9231 : /************************************************************************/
9232 :
9233 : /** Removes a field domain from the dataset.
9234 : *
9235 : * Only a few drivers will support this operation.
9236 : *
9237 : * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9238 : * support this operation. A dataset having at least some support for this
9239 : * operation should report the ODsCDeleteFieldDomain dataset capability.
9240 : *
9241 : * Anticipated failures will not be emitted through the CPLError()
9242 : * infrastructure, but will be reported in the ppszFailureReason output
9243 : * parameter.
9244 : *
9245 : * @param hDS Dataset handle.
9246 : * @param pszName The domain name.
9247 : * @param ppszFailureReason Output parameter. Will contain an error message if
9248 : * an error occurs (*ppszFailureReason to be freed
9249 : * with CPLFree). May be NULL.
9250 : * @return true in case of success.
9251 : * @since GDAL 3.3
9252 : */
9253 10 : bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
9254 : char **ppszFailureReason)
9255 : {
9256 10 : VALIDATE_POINTER1(hDS, __func__, false);
9257 10 : VALIDATE_POINTER1(pszName, __func__, false);
9258 10 : std::string failureReason;
9259 : const bool bRet =
9260 10 : GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
9261 10 : if (ppszFailureReason)
9262 : {
9263 0 : *ppszFailureReason =
9264 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9265 : }
9266 10 : return bRet;
9267 : }
9268 :
9269 : /************************************************************************/
9270 : /* UpdateFieldDomain() */
9271 : /************************************************************************/
9272 :
9273 : /** Updates an existing field domain by replacing its definition.
9274 : *
9275 : * The existing field domain with matching name will be replaced.
9276 : *
9277 : * Only a few drivers will support this operation, and some of them might only
9278 : * support it only for some types of field domains.
9279 : * At the time of writing (GDAL 3.5), only the Memory driver
9280 : * supports this operation. A dataset having at least some support for this
9281 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9282 : *
9283 : * Anticipated failures will not be emitted through the CPLError()
9284 : * infrastructure, but will be reported in the failureReason output parameter.
9285 : *
9286 : * @param domain The domain definition.
9287 : * @param failureReason Output parameter. Will contain an error message if
9288 : * an error occurs.
9289 : * @return true in case of success.
9290 : * @since GDAL 3.5
9291 : */
9292 0 : bool GDALDataset::UpdateFieldDomain(
9293 : CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9294 : std::string &failureReason)
9295 : {
9296 0 : failureReason = "UpdateFieldDomain not supported by this driver";
9297 0 : return false;
9298 : }
9299 :
9300 : /************************************************************************/
9301 : /* GDALDatasetUpdateFieldDomain() */
9302 : /************************************************************************/
9303 :
9304 : /** Updates an existing field domain by replacing its definition.
9305 : *
9306 : * The existing field domain with matching name will be replaced.
9307 : *
9308 : * Only a few drivers will support this operation, and some of them might only
9309 : * support it only for some types of field domains.
9310 : * At the time of writing (GDAL 3.5), only the Memory driver
9311 : * supports this operation. A dataset having at least some support for this
9312 : * operation should report the ODsCUpdateFieldDomain dataset capability.
9313 : *
9314 : * Anticipated failures will not be emitted through the CPLError()
9315 : * infrastructure, but will be reported in the failureReason output parameter.
9316 : *
9317 : * @param hDS Dataset handle.
9318 : * @param hFieldDomain The domain definition. Contrary to the C++ version,
9319 : * the passed object is copied.
9320 : * @param ppszFailureReason Output parameter. Will contain an error message if
9321 : * an error occurs (*ppszFailureReason to be freed
9322 : * with CPLFree). May be NULL.
9323 : * @return true in case of success.
9324 : * @since GDAL 3.5
9325 : */
9326 5 : bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
9327 : OGRFieldDomainH hFieldDomain,
9328 : char **ppszFailureReason)
9329 : {
9330 5 : VALIDATE_POINTER1(hDS, __func__, false);
9331 5 : VALIDATE_POINTER1(hFieldDomain, __func__, false);
9332 : auto poDomain = std::unique_ptr<OGRFieldDomain>(
9333 10 : OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9334 5 : if (poDomain == nullptr)
9335 0 : return false;
9336 5 : std::string failureReason;
9337 10 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
9338 5 : std::move(poDomain), failureReason);
9339 5 : if (ppszFailureReason)
9340 : {
9341 0 : *ppszFailureReason =
9342 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9343 : }
9344 5 : return bRet;
9345 : }
9346 :
9347 : /************************************************************************/
9348 : /* GetRelationshipNames() */
9349 : /************************************************************************/
9350 :
9351 : /** Returns a list of the names of all relationships stored in the dataset.
9352 : *
9353 : * @param papszOptions Driver specific options determining how relationships
9354 : * should be retrieved. Pass nullptr for default behavior.
9355 : *
9356 : * @return list of relationship names
9357 : * @since GDAL 3.6
9358 : */
9359 : std::vector<std::string>
9360 42 : GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
9361 : {
9362 42 : return {};
9363 : }
9364 :
9365 : /************************************************************************/
9366 : /* GDALDatasetGetRelationshipNames() */
9367 : /************************************************************************/
9368 :
9369 : /** Returns a list of the names of all relationships stored in the dataset.
9370 : *
9371 : * This is the same as the C++ method GDALDataset::GetRelationshipNames().
9372 : *
9373 : * @param hDS Dataset handle.
9374 : * @param papszOptions Driver specific options determining how relationships
9375 : * should be retrieved. Pass nullptr for default behavior.
9376 : *
9377 : * @return list of relationship names, to be freed with CSLDestroy()
9378 : * @since GDAL 3.6
9379 : */
9380 41 : char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
9381 : CSLConstList papszOptions)
9382 : {
9383 41 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9384 : auto names =
9385 82 : GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
9386 82 : CPLStringList res;
9387 130 : for (const auto &name : names)
9388 : {
9389 89 : res.AddString(name.c_str());
9390 : }
9391 41 : return res.StealList();
9392 : }
9393 :
9394 : /************************************************************************/
9395 : /* GetRelationship() */
9396 : /************************************************************************/
9397 :
9398 : /** Get a relationship from its name.
9399 : *
9400 : * @return the relationship, or nullptr if not found.
9401 : * @since GDAL 3.6
9402 : */
9403 : const GDALRelationship *
9404 0 : GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
9405 : {
9406 0 : return nullptr;
9407 : }
9408 :
9409 : /************************************************************************/
9410 : /* GDALDatasetGetRelationship() */
9411 : /************************************************************************/
9412 :
9413 : /** Get a relationship from its name.
9414 : *
9415 : * This is the same as the C++ method GDALDataset::GetRelationship().
9416 : *
9417 : * @param hDS Dataset handle.
9418 : * @param pszName Name of relationship.
9419 : * @return the relationship (ownership remains to the dataset), or nullptr if
9420 : * not found.
9421 : * @since GDAL 3.6
9422 : */
9423 50 : GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
9424 : const char *pszName)
9425 : {
9426 50 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9427 50 : VALIDATE_POINTER1(pszName, __func__, nullptr);
9428 50 : return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
9429 50 : GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
9430 : }
9431 :
9432 : /************************************************************************/
9433 : /* AddRelationship() */
9434 : /************************************************************************/
9435 :
9436 : /** Add a relationship to the dataset.
9437 : *
9438 : * Only a few drivers will support this operation, and some of them might only
9439 : * support it only for some types of relationships.
9440 : *
9441 : * A dataset having at least some support for this
9442 : * operation should report the GDsCAddRelationship dataset capability.
9443 : *
9444 : * Anticipated failures will not be emitted through the CPLError()
9445 : * infrastructure, but will be reported in the failureReason output parameter.
9446 : *
9447 : * When adding a many-to-many relationship
9448 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9449 : * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
9450 : * the driver to create an appropriately named and structured mapping table.
9451 : * Some dataset formats require particular naming conventions and field
9452 : * structures for the mapping table, and delegating the construction of the
9453 : * mapping table to the driver will avoid these pitfalls.
9454 : *
9455 : * @param relationship The relationship definition.
9456 : * @param failureReason Output parameter. Will contain an error message if
9457 : * an error occurs.
9458 : * @return true in case of success.
9459 : * @since GDAL 3.6
9460 : */
9461 0 : bool GDALDataset::AddRelationship(
9462 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9463 : std::string &failureReason)
9464 : {
9465 0 : failureReason = "AddRelationship not supported by this driver";
9466 0 : return false;
9467 : }
9468 :
9469 : /************************************************************************/
9470 : /* GDALDatasetAddRelationship() */
9471 : /************************************************************************/
9472 :
9473 : /** Add a relationship to the dataset.
9474 : *
9475 : * Only a few drivers will support this operation, and some of them might only
9476 : * support it only for some types of relationships.
9477 : *
9478 : * A dataset having at least some support for this
9479 : * operation should report the GDsCAddRelationship dataset capability.
9480 : *
9481 : * Anticipated failures will not be emitted through the CPLError()
9482 : * infrastructure, but will be reported in the failureReason output parameter.
9483 : *
9484 : * When adding a many-to-many relationship
9485 : * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9486 : * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
9487 : * driver to create an appropriately named and structured mapping table. Some
9488 : * dataset formats require particular naming conventions and field structures
9489 : * for the mapping table, and delegating the construction of the mapping table
9490 : * to the driver will avoid these pitfalls.
9491 : *
9492 : * @param hDS Dataset handle.
9493 : * @param hRelationship The relationship definition. Contrary to the C++
9494 : * version, the passed object is copied.
9495 : * @param ppszFailureReason Output parameter. Will contain an error message if
9496 : * an error occurs (*ppszFailureReason to be freed
9497 : * with CPLFree). May be NULL.
9498 : * @return true in case of success.
9499 : * @since GDAL 3.6
9500 : */
9501 42 : bool GDALDatasetAddRelationship(GDALDatasetH hDS,
9502 : GDALRelationshipH hRelationship,
9503 : char **ppszFailureReason)
9504 : {
9505 42 : VALIDATE_POINTER1(hDS, __func__, false);
9506 42 : VALIDATE_POINTER1(hRelationship, __func__, false);
9507 : std::unique_ptr<GDALRelationship> poRelationship(
9508 84 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9509 42 : std::string failureReason;
9510 84 : const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
9511 42 : std::move(poRelationship), failureReason);
9512 42 : if (ppszFailureReason)
9513 : {
9514 0 : *ppszFailureReason =
9515 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9516 : }
9517 42 : return bRet;
9518 : }
9519 :
9520 : /************************************************************************/
9521 : /* DeleteRelationship() */
9522 : /************************************************************************/
9523 :
9524 : /** Removes a relationship from the dataset.
9525 : *
9526 : * Only a few drivers will support this operation.
9527 : *
9528 : * A dataset having at least some support for this
9529 : * operation should report the GDsCDeleteRelationship dataset capability.
9530 : *
9531 : * Anticipated failures will not be emitted through the CPLError()
9532 : * infrastructure, but will be reported in the failureReason output parameter.
9533 : *
9534 : * @param name The relationship name.
9535 : * @param failureReason Output parameter. Will contain an error message if
9536 : * an error occurs.
9537 : * @return true in case of success.
9538 : * @since GDAL 3.6
9539 : */
9540 0 : bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
9541 : std::string &failureReason)
9542 : {
9543 0 : failureReason = "DeleteRelationship not supported by this driver";
9544 0 : return false;
9545 : }
9546 :
9547 : /************************************************************************/
9548 : /* GDALDatasetDeleteRelationship() */
9549 : /************************************************************************/
9550 :
9551 : /** Removes a relationship from the dataset.
9552 : *
9553 : * Only a few drivers will support this operation.
9554 : *
9555 : * A dataset having at least some support for this
9556 : * operation should report the GDsCDeleteRelationship dataset capability.
9557 : *
9558 : * Anticipated failures will not be emitted through the CPLError()
9559 : * infrastructure, but will be reported in the ppszFailureReason output
9560 : * parameter.
9561 : *
9562 : * @param hDS Dataset handle.
9563 : * @param pszName The relationship name.
9564 : * @param ppszFailureReason Output parameter. Will contain an error message if
9565 : * an error occurs (*ppszFailureReason to be freed
9566 : * with CPLFree). May be NULL.
9567 : * @return true in case of success.
9568 : * @since GDAL 3.6
9569 : */
9570 6 : bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
9571 : char **ppszFailureReason)
9572 : {
9573 6 : VALIDATE_POINTER1(hDS, __func__, false);
9574 6 : VALIDATE_POINTER1(pszName, __func__, false);
9575 6 : std::string failureReason;
9576 12 : const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
9577 6 : pszName, failureReason);
9578 6 : if (ppszFailureReason)
9579 : {
9580 0 : *ppszFailureReason =
9581 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9582 : }
9583 6 : return bRet;
9584 : }
9585 :
9586 : /************************************************************************/
9587 : /* UpdateRelationship() */
9588 : /************************************************************************/
9589 :
9590 : /** Updates an existing relationship by replacing its definition.
9591 : *
9592 : * The existing relationship with matching name will be replaced.
9593 : *
9594 : * Only a few drivers will support this operation, and some of them might only
9595 : * support it only for some types of relationships.
9596 : * A dataset having at least some support for this
9597 : * operation should report the GDsCUpdateRelationship dataset capability.
9598 : *
9599 : * Anticipated failures will not be emitted through the CPLError()
9600 : * infrastructure, but will be reported in the failureReason output parameter.
9601 : *
9602 : * @param relationship The relationship definition.
9603 : * @param failureReason Output parameter. Will contain an error message if
9604 : * an error occurs.
9605 : * @return true in case of success.
9606 : * @since GDAL 3.6
9607 : */
9608 0 : bool GDALDataset::UpdateRelationship(
9609 : CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9610 : std::string &failureReason)
9611 : {
9612 0 : failureReason = "UpdateRelationship not supported by this driver";
9613 0 : return false;
9614 : }
9615 :
9616 : /************************************************************************/
9617 : /* GDALDatasetUpdateRelationship() */
9618 : /************************************************************************/
9619 :
9620 : /** Updates an existing relationship by replacing its definition.
9621 : *
9622 : * The existing relationship with matching name will be replaced.
9623 : *
9624 : * Only a few drivers will support this operation, and some of them might only
9625 : * support it only for some types of relationships.
9626 : * A dataset having at least some support for this
9627 : * operation should report the GDsCUpdateRelationship dataset capability.
9628 : *
9629 : * Anticipated failures will not be emitted through the CPLError()
9630 : * infrastructure, but will be reported in the failureReason output parameter.
9631 : *
9632 : * @param hDS Dataset handle.
9633 : * @param hRelationship The relationship definition. Contrary to the C++
9634 : * version, the passed object is copied.
9635 : * @param ppszFailureReason Output parameter. Will contain an error message if
9636 : * an error occurs (*ppszFailureReason to be freed
9637 : * with CPLFree). May be NULL.
9638 : * @return true in case of success.
9639 : * @since GDAL 3.5
9640 : */
9641 9 : bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
9642 : GDALRelationshipH hRelationship,
9643 : char **ppszFailureReason)
9644 : {
9645 9 : VALIDATE_POINTER1(hDS, __func__, false);
9646 9 : VALIDATE_POINTER1(hRelationship, __func__, false);
9647 : std::unique_ptr<GDALRelationship> poRelationship(
9648 18 : new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9649 9 : std::string failureReason;
9650 18 : const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
9651 9 : std::move(poRelationship), failureReason);
9652 9 : if (ppszFailureReason)
9653 : {
9654 0 : *ppszFailureReason =
9655 0 : failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9656 : }
9657 9 : return bRet;
9658 : }
9659 :
9660 : /************************************************************************/
9661 : /* GDALDatasetSetQueryLoggerFunc() */
9662 : /************************************************************************/
9663 :
9664 : /**
9665 : * Sets the SQL query logger callback.
9666 : *
9667 : * When supported by the driver, the callback will be called with
9668 : * the executed SQL text, the error message, the execution time in milliseconds,
9669 : * the number of records fetched/affected and the client status data.
9670 : *
9671 : * A value of -1 in the execution time or in the number of records indicates
9672 : * that the values are unknown.
9673 : *
9674 : * @param hDS Dataset handle.
9675 : * @param pfnQueryLoggerFunc Callback function
9676 : * @param poQueryLoggerArg Opaque client status data
9677 : * @return true in case of success.
9678 : * @since GDAL 3.7
9679 : */
9680 1 : bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
9681 : GDALQueryLoggerFunc pfnQueryLoggerFunc,
9682 : void *poQueryLoggerArg)
9683 : {
9684 1 : VALIDATE_POINTER1(hDS, __func__, false);
9685 2 : return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
9686 1 : poQueryLoggerArg);
9687 : }
9688 :
9689 : //! @cond Doxygen_Suppress
9690 :
9691 : /************************************************************************/
9692 : /* SetEnableOverviews() */
9693 : /************************************************************************/
9694 :
9695 7341 : void GDALDataset::SetEnableOverviews(bool bEnable)
9696 : {
9697 7341 : if (m_poPrivate)
9698 : {
9699 7341 : m_poPrivate->m_bOverviewsEnabled = bEnable;
9700 : }
9701 7341 : }
9702 :
9703 : /************************************************************************/
9704 : /* AreOverviewsEnabled() */
9705 : /************************************************************************/
9706 :
9707 1341000 : bool GDALDataset::AreOverviewsEnabled() const
9708 : {
9709 1341000 : return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
9710 : }
9711 :
9712 : /************************************************************************/
9713 : /* IsAllBands() */
9714 : /************************************************************************/
9715 :
9716 66 : bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
9717 : {
9718 66 : if (nBands != nBandCount)
9719 1 : return false;
9720 65 : if (panBandList)
9721 : {
9722 3 : for (int i = 0; i < nBandCount; ++i)
9723 : {
9724 2 : if (panBandList[i] != i + 1)
9725 1 : return false;
9726 : }
9727 : }
9728 64 : return true;
9729 : }
9730 :
9731 : //! @endcond
9732 :
9733 : /************************************************************************/
9734 : /* GetCompressionFormats() */
9735 : /************************************************************************/
9736 :
9737 : /** Return the compression formats that can be natively obtained for the
9738 : * window of interest and requested bands.
9739 : *
9740 : * For example, a tiled dataset may be able to return data in a compressed
9741 : * format if the window of interest matches exactly a tile. For some formats,
9742 : * drivers may also be able to merge several tiles together (not currently
9743 : * implemented though).
9744 : *
9745 : * Each format string is a pseudo MIME type, whose first part can be passed
9746 : * as the pszFormat argument of ReadCompressedData(), with additional
9747 : * parameters specified as key=value with a semi-colon separator.
9748 : *
9749 : * The amount and types of optional parameters passed after the MIME type is
9750 : * format dependent, and driver dependent (some drivers might not be able to
9751 : * return those extra information without doing a rather costly processing).
9752 : *
9753 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9754 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9755 : * consequently "JPEG" can be passed as the pszFormat argument of
9756 : * ReadCompressedData(). For JPEG, implementations can use the
9757 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9758 : * above from a JPEG codestream.
9759 : *
9760 : * Several values might be returned. For example,
9761 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9762 : * if the JPEGXL codestream includes a JPEG reconstruction box.
9763 : *
9764 : * In the general case this method will return an empty list.
9765 : *
9766 : * This is the same as C function GDALDatasetGetCompressionFormats().
9767 : *
9768 : * @param nXOff The pixel offset to the top left corner of the region
9769 : * of the band to be accessed. This would be zero to start from the left side.
9770 : *
9771 : * @param nYOff The line offset to the top left corner of the region
9772 : * of the band to be accessed. This would be zero to start from the top.
9773 : *
9774 : * @param nXSize The width of the region of the band to be accessed in pixels.
9775 : *
9776 : * @param nYSize The height of the region of the band to be accessed in lines.
9777 : *
9778 : * @param nBandCount the number of bands being requested.
9779 : *
9780 : * @param panBandList the list of nBandCount band numbers.
9781 : * Note band numbers are 1 based. This may be NULL to select the first
9782 : * nBandCount bands.
9783 : *
9784 : * @return a list of compatible formats (which may be empty)
9785 : *
9786 : * For example, to check if native compression format(s) are available on the
9787 : * whole image:
9788 : * \code{.cpp}
9789 : * const CPLStringList aosFormats =
9790 : * poDataset->GetCompressionFormats(0, 0,
9791 : * poDataset->GetRasterXSize(),
9792 : * poDataset->GetRasterYSize(),
9793 : * poDataset->GetRasterCount(),
9794 : * nullptr);
9795 : * for( const char* pszFormat: aosFormats )
9796 : * {
9797 : * // Remove optional parameters and just print out the MIME type.
9798 : * const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
9799 : * printf("Found format %s\n, aosTokens[0]);
9800 : * }
9801 : * \endcode
9802 : *
9803 : * @since GDAL 3.7
9804 : */
9805 : CPLStringList
9806 0 : GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
9807 : CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
9808 : CPL_UNUSED int nBandCount,
9809 : CPL_UNUSED const int *panBandList)
9810 : {
9811 0 : return CPLStringList();
9812 : }
9813 :
9814 : /************************************************************************/
9815 : /* GDALDatasetGetCompressionFormats() */
9816 : /************************************************************************/
9817 :
9818 : /** Return the compression formats that can be natively obtained for the
9819 : * window of interest and requested bands.
9820 : *
9821 : * For example, a tiled dataset may be able to return data in a compressed
9822 : * format if the window of interest matches exactly a tile. For some formats,
9823 : * drivers may also be able to merge several tiles together (not currently
9824 : * implemented though).
9825 : *
9826 : * Each format string is a pseudo MIME type, whose first part can be passed
9827 : * as the pszFormat argument of ReadCompressedData(), with additional
9828 : * parameters specified as key=value with a semi-colon separator.
9829 : *
9830 : * The amount and types of optional parameters passed after the MIME type is
9831 : * format dependent, and driver dependent (some drivers might not be able to
9832 : * return those extra information without doing a rather costly processing).
9833 : *
9834 : * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9835 : * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9836 : * consequently "JPEG" can be passed as the pszFormat argument of
9837 : * ReadCompressedData(). For JPEG, implementations can use the
9838 : * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9839 : * above from a JPEG codestream.
9840 : *
9841 : * Several values might be returned. For example,
9842 : * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9843 : * if the JPEGXL codestream includes a JPEG reconstruction box.
9844 : *
9845 : * In the general case this method will return an empty list.
9846 : *
9847 : * This is the same as C++ method GDALDataset::GetCompressionFormats().
9848 : *
9849 : * @param hDS Dataset handle.
9850 : *
9851 : * @param nXOff The pixel offset to the top left corner of the region
9852 : * of the band to be accessed. This would be zero to start from the left side.
9853 : *
9854 : * @param nYOff The line offset to the top left corner of the region
9855 : * of the band to be accessed. This would be zero to start from the top.
9856 : *
9857 : * @param nXSize The width of the region of the band to be accessed in pixels.
9858 : *
9859 : * @param nYSize The height of the region of the band to be accessed in lines.
9860 : *
9861 : * @param nBandCount the number of bands being requested.
9862 : *
9863 : * @param panBandList the list of nBandCount band numbers.
9864 : * Note band numbers are 1 based. This may be NULL to select the first
9865 : * nBandCount bands.
9866 : *
9867 : * @return a list of compatible formats (which may be empty) that should be
9868 : * freed with CSLDestroy(), or nullptr.
9869 : *
9870 : * @since GDAL 3.7
9871 : */
9872 9 : char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
9873 : int nXSize, int nYSize, int nBandCount,
9874 : const int *panBandList)
9875 : {
9876 9 : VALIDATE_POINTER1(hDS, __func__, nullptr);
9877 9 : return GDALDataset::FromHandle(hDS)
9878 9 : ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
9879 9 : panBandList)
9880 9 : .StealList();
9881 : }
9882 :
9883 : /************************************************************************/
9884 : /* ReadCompressedData() */
9885 : /************************************************************************/
9886 :
9887 : /** Return the compressed content that can be natively obtained for the
9888 : * window of interest and requested bands.
9889 : *
9890 : * For example, a tiled dataset may be able to return data in compressed format
9891 : * if the window of interest matches exactly a tile. For some formats, drivers
9892 : * may also be example to merge several tiles together (not currently
9893 : * implemented though).
9894 : *
9895 : * The implementation should make sure that the content returned forms a valid
9896 : * standalone file. For example, for the GeoTIFF implementation of this method,
9897 : * when extracting a JPEG tile, the method will automatically add the content
9898 : * of the JPEG Huffman and/or quantization tables that might be stored in the
9899 : * TIFF JpegTables tag, and not in tile data itself.
9900 : *
9901 : * In the general case this method will return CE_Failure.
9902 : *
9903 : * This is the same as C function GDALDatasetReadCompressedData().
9904 : *
9905 : * @param pszFormat Requested compression format (e.g. "JPEG",
9906 : * "WEBP", "JXL"). This is the MIME type of one of the values
9907 : * returned by GetCompressionFormats(). The format string is designed to
9908 : * potentially include at a later point key=value optional parameters separated
9909 : * by a semi-colon character. At time of writing, none are implemented.
9910 : * ReadCompressedData() implementations should verify optional parameters and
9911 : * return CE_Failure if they cannot support one of them.
9912 : *
9913 : * @param nXOff The pixel offset to the top left corner of the region
9914 : * of the band to be accessed. This would be zero to start from the left side.
9915 : *
9916 : * @param nYOff The line offset to the top left corner of the region
9917 : * of the band to be accessed. This would be zero to start from the top.
9918 : *
9919 : * @param nXSize The width of the region of the band to be accessed in pixels.
9920 : *
9921 : * @param nYSize The height of the region of the band to be accessed in lines.
9922 : *
9923 : * @param nBandCount the number of bands being requested.
9924 : *
9925 : * @param panBandList the list of nBandCount band numbers.
9926 : * Note band numbers are 1 based. This may be NULL to select the first
9927 : * nBandCount bands.
9928 : *
9929 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
9930 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
9931 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
9932 : * buffer will be filled with the compressed data, provided that pnBufferSize
9933 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
9934 : * of *ppBuffer, is sufficiently large to hold the data.
9935 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
9936 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
9937 : * free it with VSIFree().
9938 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
9939 : * but *pnBufferSize will be updated with an upper bound of the size that would
9940 : * be necessary to hold it (if pnBufferSize != nullptr).
9941 : *
9942 : * @param pnBufferSize Output buffer size, or nullptr.
9943 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
9944 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
9945 : * method is successful, *pnBufferSize will be updated with the actual size
9946 : * used.
9947 : *
9948 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
9949 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
9950 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
9951 : * *ppszDetailedFormat might contain strings like
9952 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
9953 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
9954 : * The string will contain at least as much information as what
9955 : * GetCompressionFormats() returns, and potentially more when
9956 : * ppBuffer != nullptr.
9957 : *
9958 : * @return CE_None in case of success, CE_Failure otherwise.
9959 : *
9960 : * For example, to request JPEG content on the whole image and let GDAL deal
9961 : * with the buffer allocation.
9962 : * \code{.cpp}
9963 : * void* pBuffer = nullptr;
9964 : * size_t nBufferSize = 0;
9965 : * CPLErr eErr =
9966 : * poDataset->ReadCompressedData("JPEG",
9967 : * 0, 0,
9968 : * poDataset->GetRasterXSize(),
9969 : * poDataset->GetRasterYSize(),
9970 : * poDataset->GetRasterCount(),
9971 : * nullptr, // panBandList
9972 : * &pBuffer,
9973 : * &nBufferSize,
9974 : * nullptr // ppszDetailedFormat
9975 : * );
9976 : * if (eErr == CE_None)
9977 : * {
9978 : * CPLAssert(pBuffer != nullptr);
9979 : * CPLAssert(nBufferSize > 0);
9980 : * VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
9981 : * if (fp)
9982 : * {
9983 : * VSIFWriteL(pBuffer, nBufferSize, 1, fp);
9984 : * VSIFCloseL(fp);
9985 : * }
9986 : * VSIFree(pBuffer);
9987 : * }
9988 : * \endcode
9989 : *
9990 : * Or to manage the buffer allocation on your side:
9991 : * \code{.cpp}
9992 : * size_t nUpperBoundBufferSize = 0;
9993 : * CPLErr eErr =
9994 : * poDataset->ReadCompressedData("JPEG",
9995 : * 0, 0,
9996 : * poDataset->GetRasterXSize(),
9997 : * poDataset->GetRasterYSize(),
9998 : * poDataset->GetRasterCount(),
9999 : * nullptr, // panBandList
10000 : * nullptr, // ppBuffer,
10001 : * &nUpperBoundBufferSize,
10002 : * nullptr // ppszDetailedFormat
10003 : * );
10004 : * if (eErr == CE_None)
10005 : * {
10006 : * std::vector<uint8_t> myBuffer;
10007 : * myBuffer.resize(nUpperBoundBufferSize);
10008 : * void* pBuffer = myBuffer.data();
10009 : * size_t nActualSize = nUpperBoundBufferSize;
10010 : * char* pszDetailedFormat = nullptr;
10011 : * // We also request detailed format, but we could have passed it to
10012 : * // nullptr as well.
10013 : * eErr =
10014 : * poDataset->ReadCompressedData("JPEG",
10015 : * 0, 0,
10016 : * poDataset->GetRasterXSize(),
10017 : * poDataset->GetRasterYSize(),
10018 : * poDataset->GetRasterCount(),
10019 : * nullptr, // panBandList
10020 : * &pBuffer,
10021 : * &nActualSize,
10022 : * &pszDetailedFormat);
10023 : * if (eErr == CE_None)
10024 : * {
10025 : * CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10026 : * CPLAssert(nActualSize <= nUpperBoundBufferSize);
10027 : * myBuffer.resize(nActualSize);
10028 : * // do something useful
10029 : * VSIFree(pszDetailedFormat);
10030 : * }
10031 : * }
10032 : * \endcode
10033 : *
10034 : * @since GDAL 3.7
10035 : */
10036 424 : CPLErr GDALDataset::ReadCompressedData(
10037 : CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10038 : CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10039 : CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10040 : CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10041 : CPL_UNUSED char **ppszDetailedFormat)
10042 : {
10043 424 : return CE_Failure;
10044 : }
10045 :
10046 : /************************************************************************/
10047 : /* GDALDatasetReadCompressedData() */
10048 : /************************************************************************/
10049 :
10050 : /** Return the compressed content that can be natively obtained for the
10051 : * window of interest and requested bands.
10052 : *
10053 : * For example, a tiled dataset may be able to return data in compressed format
10054 : * if the window of interest matches exactly a tile. For some formats, drivers
10055 : * may also be example to merge several tiles together (not currently
10056 : * implemented though).
10057 : *
10058 : * The implementation should make sure that the content returned forms a valid
10059 : * standalone file. For example, for the GeoTIFF implementation of this method,
10060 : * when extracting a JPEG tile, the method will automatically adds the content
10061 : * of the JPEG Huffman and/or quantization tables that might be stored in the
10062 : * TIFF JpegTables tag, and not in tile data itself.
10063 : *
10064 : * In the general case this method will return CE_Failure.
10065 : *
10066 : * This is the same as C++ method GDALDataset:ReadCompressedData().
10067 : *
10068 : * @param hDS Dataset handle.
10069 : *
10070 : * @param pszFormat Requested compression format (e.g. "JPEG",
10071 : * "WEBP", "JXL"). This is the MIME type of one of the values
10072 : * returned by GetCompressionFormats(). The format string is designed to
10073 : * potentially include at a later point key=value optional parameters separated
10074 : * by a semi-colon character. At time of writing, none are implemented.
10075 : * ReadCompressedData() implementations should verify optional parameters and
10076 : * return CE_Failure if they cannot support one of them.
10077 : *
10078 : * @param nXOff The pixel offset to the top left corner of the region
10079 : * of the band to be accessed. This would be zero to start from the left side.
10080 : *
10081 : * @param nYOff The line offset to the top left corner of the region
10082 : * of the band to be accessed. This would be zero to start from the top.
10083 : *
10084 : * @param nXSize The width of the region of the band to be accessed in pixels.
10085 : *
10086 : * @param nYSize The height of the region of the band to be accessed in lines.
10087 : *
10088 : * @param nBandCount the number of bands being requested.
10089 : *
10090 : * @param panBandList the list of nBandCount band numbers.
10091 : * Note band numbers are 1 based. This may be NULL to select the first
10092 : * nBandCount bands.
10093 : *
10094 : * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10095 : * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10096 : * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10097 : * buffer will be filled with the compressed data, provided that pnBufferSize
10098 : * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10099 : * of *ppBuffer, is sufficiently large to hold the data.
10100 : * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10101 : * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10102 : * free it with VSIFree().
10103 : * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10104 : * but *pnBufferSize will be updated with an upper bound of the size that would
10105 : * be necessary to hold it (if pnBufferSize != nullptr).
10106 : *
10107 : * @param pnBufferSize Output buffer size, or nullptr.
10108 : * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10109 : * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10110 : * method is successful, *pnBufferSize will be updated with the actual size
10111 : * used.
10112 : *
10113 : * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10114 : * If ppszDetailedFormat is not nullptr, then, on success, the method will
10115 : * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10116 : * *ppszDetailedFormat might contain strings like
10117 : * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10118 : * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10119 : * The string will contain at least as much information as what
10120 : * GetCompressionFormats() returns, and potentially more when
10121 : * ppBuffer != nullptr.
10122 : *
10123 : * @return CE_None in case of success, CE_Failure otherwise.
10124 : *
10125 : * @since GDAL 3.7
10126 : */
10127 28 : CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10128 : int nXOff, int nYOff, int nXSize,
10129 : int nYSize, int nBandCount,
10130 : const int *panBandList, void **ppBuffer,
10131 : size_t *pnBufferSize,
10132 : char **ppszDetailedFormat)
10133 : {
10134 28 : VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10135 56 : return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10136 : pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10137 28 : ppBuffer, pnBufferSize, ppszDetailedFormat);
10138 : }
|