Coverage Report

Created: 2025-08-28 06:57

/src/gdal/gcore/gdaldataset.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  GDAL Core
4
 * Purpose:  Base class for raster file formats.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 1998, 2003, Frank Warmerdam
9
 * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "cpl_port.h"
15
#include "gdal.h"
16
#include "gdal_priv.h"
17
18
#include <array>
19
#include <climits>
20
#include <cstdarg>
21
#include <cstdio>
22
#include <cstdlib>
23
#include <cstring>
24
#include <algorithm>
25
#include <map>
26
#include <mutex>
27
#include <new>
28
#include <set>
29
#include <string>
30
#include <utility>
31
32
#include "cpl_conv.h"
33
#include "cpl_error.h"
34
#include "cpl_hash_set.h"
35
#include "cpl_multiproc.h"
36
#include "cpl_progress.h"
37
#include "cpl_string.h"
38
#include "cpl_vsi.h"
39
#include "cpl_vsi_error.h"
40
#include "gdal_alg.h"
41
#include "ogr_api.h"
42
#include "ogr_attrind.h"
43
#include "ogr_core.h"
44
#include "ogr_feature.h"
45
#include "ogr_featurestyle.h"
46
#include "ogr_gensql.h"
47
#include "ogr_geometry.h"
48
#include "ogr_p.h"
49
#include "ogr_spatialref.h"
50
#include "ogr_srs_api.h"
51
#include "ograpispy.h"
52
#include "ogrsf_frmts.h"
53
#include "ogrunionlayer.h"
54
#include "ogr_swq.h"
55
56
#include "../frmts/derived/derivedlist.h"
57
58
#ifdef SQLITE_ENABLED
59
#include "../sqlite/ogrsqliteexecutesql.h"
60
#endif
61
62
extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
63
64
CPL_C_START
65
GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
66
                                           int nYOff, int nXSize, int nYSize,
67
                                           void *pBuf, int nBufXSize,
68
                                           int nBufYSize, GDALDataType eBufType,
69
                                           int nBandCount, int *panBandMap,
70
                                           int nPixelSpace, int nLineSpace,
71
                                           int nBandSpace, char **papszOptions);
72
CPL_C_END
73
74
enum class GDALAllowReadWriteMutexState
75
{
76
    RW_MUTEX_STATE_UNKNOWN,
77
    RW_MUTEX_STATE_ALLOWED,
78
    RW_MUTEX_STATE_DISABLED
79
};
80
81
const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
82
const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
83
84
class GDALDataset::Private
85
{
86
    CPL_DISALLOW_COPY_ASSIGN(Private)
87
88
  public:
89
    CPLMutex *hMutex = nullptr;
90
    std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
91
#ifdef DEBUG_EXTRA
92
    std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
93
#endif
94
    GDALAllowReadWriteMutexState eStateReadWriteMutex =
95
        GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
96
    int nCurrentLayerIdx = 0;
97
    int nLayerCount = -1;
98
    GIntBig nFeatureReadInLayer = 0;
99
    GIntBig nFeatureReadInDataset = 0;
100
    GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
101
    GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
102
    OGRLayer *poCurrentLayer = nullptr;
103
104
    std::mutex m_oMutexWKT{};
105
106
    char *m_pszWKTCached = nullptr;
107
    OGRSpatialReference *m_poSRSCached = nullptr;
108
    char *m_pszWKTGCPCached = nullptr;
109
    OGRSpatialReference *m_poSRSGCPCached = nullptr;
110
111
    GDALDataset *poParentDataset = nullptr;
112
113
    bool m_bOverviewsEnabled = true;
114
115
    std::vector<int>
116
        m_anBandMap{};  // used by RasterIO(). Values are 1, 2, etc.
117
118
0
    Private() = default;
119
};
120
121
struct SharedDatasetCtxt
122
{
123
    // PID of the thread that mark the dataset as shared
124
    // This may not be the actual PID, but the responsiblePID.
125
    GIntBig nPID;
126
    char *pszDescription;
127
    char *pszConcatenatedOpenOptions;
128
    int nOpenFlags;
129
130
    GDALDataset *poDS;
131
};
132
133
// Set of datasets opened as shared datasets (with GDALOpenShared)
134
// The values in the set are of type SharedDatasetCtxt.
135
static CPLHashSet *phSharedDatasetSet = nullptr;
136
137
// Set of all datasets created in the constructor of GDALDataset.
138
// In the case of a shared dataset, memorize the PID of the thread
139
// that marked the dataset as shared, so that we can remove it from
140
// the phSharedDatasetSet in the destructor of the dataset, even
141
// if GDALClose is called from a different thread.
142
static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
143
144
static CPLMutex *hDLMutex = nullptr;
145
146
// Static array of all datasets. Used by GDALGetOpenDatasets.
147
// Not thread-safe. See GDALGetOpenDatasets.
148
static GDALDataset **ppDatasets = nullptr;
149
150
static unsigned long GDALSharedDatasetHashFunc(const void *elt)
151
0
{
152
0
    const SharedDatasetCtxt *psStruct =
153
0
        static_cast<const SharedDatasetCtxt *>(elt);
154
0
    return static_cast<unsigned long>(
155
0
        CPLHashSetHashStr(psStruct->pszDescription) ^
156
0
        CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
157
0
        psStruct->nOpenFlags ^ psStruct->nPID);
158
0
}
159
160
static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
161
0
{
162
0
    const SharedDatasetCtxt *psStruct1 =
163
0
        static_cast<const SharedDatasetCtxt *>(elt1);
164
0
    const SharedDatasetCtxt *psStruct2 =
165
0
        static_cast<const SharedDatasetCtxt *>(elt2);
166
0
    return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
167
0
           strcmp(psStruct1->pszConcatenatedOpenOptions,
168
0
                  psStruct2->pszConcatenatedOpenOptions) == 0 &&
169
0
           psStruct1->nPID == psStruct2->nPID &&
170
0
           psStruct1->nOpenFlags == psStruct2->nOpenFlags;
171
0
}
172
173
static void GDALSharedDatasetFreeFunc(void *elt)
174
0
{
175
0
    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
176
0
    CPLFree(psStruct->pszDescription);
177
0
    CPLFree(psStruct->pszConcatenatedOpenOptions);
178
0
    CPLFree(psStruct);
179
0
}
180
181
static std::string
182
GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
183
0
{
184
0
    std::string osStr;
185
0
    for (const char *pszOption : cpl::Iterate(papszOpenOptions))
186
0
        osStr += pszOption;
187
0
    return osStr;
188
0
}
189
190
/************************************************************************/
191
/* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
192
/************************************************************************/
193
194
// The open-shared mutex must be used by the ProxyPool too.
195
CPLMutex **GDALGetphDLMutex()
196
0
{
197
0
    return &hDLMutex;
198
0
}
199
200
// The current thread will act in the behalf of the thread of PID
201
// responsiblePID.
202
void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
203
0
{
204
0
    GIntBig *pResponsiblePID =
205
0
        static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
206
0
    if (pResponsiblePID == nullptr)
207
0
    {
208
0
        pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
209
0
        CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
210
0
    }
211
0
    *pResponsiblePID = responsiblePID;
212
0
}
213
214
// Get the PID of the thread that the current thread will act in the behalf of
215
// By default : the current thread acts in the behalf of itself.
216
GIntBig GDALGetResponsiblePIDForCurrentThread()
217
0
{
218
0
    GIntBig *pResponsiblePID =
219
0
        static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
220
0
    if (pResponsiblePID == nullptr)
221
0
        return CPLGetPID();
222
0
    return *pResponsiblePID;
223
0
}
224
225
/************************************************************************/
226
/* ==================================================================== */
227
/*                             GDALDataset                              */
228
/* ==================================================================== */
229
/************************************************************************/
230
231
/**
232
 * \class GDALDataset "gdal_priv.h"
233
 *
234
 * A dataset encapsulating one or more raster bands.  Details are further
235
 * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
236
 * Raster Data Model</a>.
237
 *
238
 * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
239
 * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
240
 * dataset.
241
 */
242
243
/************************************************************************/
244
/*                            GDALDataset()                             */
245
/************************************************************************/
246
247
//! @cond Doxygen_Suppress
248
GDALDataset::GDALDataset()
249
0
    : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
250
0
{
251
0
}
252
253
GDALDataset::GDALDataset(int bForceCachedIOIn)
254
0
    : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
255
0
      m_poPrivate(new(std::nothrow) GDALDataset::Private)
256
0
{
257
0
}
258
259
//! @endcond
260
261
/************************************************************************/
262
/*                            ~GDALDataset()                            */
263
/************************************************************************/
264
265
/**
266
 * \brief Destroy an open GDALDataset.
267
 *
268
 * This is the accepted method of closing a GDAL dataset and deallocating
269
 * all resources associated with it.
270
 *
271
 * Equivalent of the C callable GDALClose().  Except that GDALClose() first
272
 * decrements the reference count, and then closes only if it has dropped to
273
 * zero.
274
 *
275
 * For Windows users, it is not recommended to use the delete operator on the
276
 * dataset object because of known issues when allocating and freeing memory
277
 * across module boundaries. Calling GDALClose() is then a better option.
278
 */
279
280
GDALDataset::~GDALDataset()
281
282
0
{
283
    // we don't want to report destruction of datasets that
284
    // were never really open or meant as internal
285
0
    if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
286
0
    {
287
0
        if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
288
0
            CPLDebug("GDAL",
289
0
                     "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
290
0
                     GetDescription(), this, static_cast<int>(CPLGetPID()),
291
0
                     static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
292
0
        else
293
0
            CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
294
0
    }
295
296
0
    if (IsMarkedSuppressOnClose())
297
0
    {
298
0
        if (poDriver == nullptr ||
299
            // Someone issuing Create("foo.tif") on a
300
            // memory driver doesn't expect files with those names to be deleted
301
            // on a file system...
302
            // This is somewhat messy. Ideally there should be a way for the
303
            // driver to overload the default behavior
304
0
            (!EQUAL(poDriver->GetDescription(), "MEM") &&
305
0
             !EQUAL(poDriver->GetDescription(), "Memory")))
306
0
        {
307
0
            VSIUnlink(GetDescription());
308
0
        }
309
0
    }
310
311
    /* -------------------------------------------------------------------- */
312
    /*      Remove dataset from the "open" dataset list.                    */
313
    /* -------------------------------------------------------------------- */
314
0
    if (!bIsInternal)
315
0
    {
316
0
        CPLMutexHolderD(&hDLMutex);
317
0
        if (poAllDatasetMap)
318
0
        {
319
0
            std::map<GDALDataset *, GIntBig>::iterator oIter =
320
0
                poAllDatasetMap->find(this);
321
0
            CPLAssert(oIter != poAllDatasetMap->end());
322
323
0
            UnregisterFromSharedDataset();
324
325
0
            poAllDatasetMap->erase(oIter);
326
327
0
            if (poAllDatasetMap->empty())
328
0
            {
329
0
                delete poAllDatasetMap;
330
0
                poAllDatasetMap = nullptr;
331
0
                if (phSharedDatasetSet)
332
0
                {
333
0
                    CPLHashSetDestroy(phSharedDatasetSet);
334
0
                }
335
0
                phSharedDatasetSet = nullptr;
336
0
                CPLFree(ppDatasets);
337
0
                ppDatasets = nullptr;
338
0
            }
339
0
        }
340
0
    }
341
342
    /* -------------------------------------------------------------------- */
343
    /*      Destroy the raster bands if they exist.                         */
344
    /* -------------------------------------------------------------------- */
345
0
    for (int i = 0; i < nBands && papoBands != nullptr; ++i)
346
0
    {
347
0
        if (papoBands[i] != nullptr)
348
0
            delete papoBands[i];
349
0
        papoBands[i] = nullptr;
350
0
    }
351
352
0
    CPLFree(papoBands);
353
354
0
    if (m_poStyleTable)
355
0
    {
356
0
        delete m_poStyleTable;
357
0
        m_poStyleTable = nullptr;
358
0
    }
359
360
0
    if (m_poPrivate != nullptr)
361
0
    {
362
0
        if (m_poPrivate->hMutex != nullptr)
363
0
            CPLDestroyMutex(m_poPrivate->hMutex);
364
365
0
#if defined(__COVERITY__) || defined(DEBUG)
366
        // Not needed since at destruction there is no risk of concurrent use.
367
0
        std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
368
0
#endif
369
0
        CPLFree(m_poPrivate->m_pszWKTCached);
370
0
        if (m_poPrivate->m_poSRSCached)
371
0
        {
372
0
            m_poPrivate->m_poSRSCached->Release();
373
0
        }
374
0
        CPLFree(m_poPrivate->m_pszWKTGCPCached);
375
0
        if (m_poPrivate->m_poSRSGCPCached)
376
0
        {
377
0
            m_poPrivate->m_poSRSGCPCached->Release();
378
0
        }
379
0
    }
380
381
0
    delete m_poPrivate;
382
383
0
    CSLDestroy(papszOpenOptions);
384
0
}
385
386
/************************************************************************/
387
/*                             Close()                                  */
388
/************************************************************************/
389
390
/** Do final cleanup before a dataset is destroyed.
391
 *
392
 * This method is typically called by GDALClose() or the destructor of a
393
 * GDALDataset subclass. It might also be called by C++ users before
394
 * destroying a dataset. It should not be called on a shared dataset whose
395
 * reference count is greater than one.
396
 *
397
 * It gives a last chance to the closing process to return an error code if
398
 * something goes wrong, in particular in creation / update scenarios where
399
 * file write or network communication might occur when finalizing the dataset.
400
 *
401
 * Implementations should be robust to this method to be called several times
402
 * (on subsequent calls, it should do nothing and return CE_None).
403
 * Once it has been called, no other method than Close() or the dataset
404
 * destructor should be called. RasterBand or OGRLayer owned by the dataset
405
 * should be assumed as no longer being valid.
406
 *
407
 * If a driver implements this method, it must also call it from its
408
 * dataset destructor.
409
 *
410
 * A typical implementation might look as the following
411
 * \code{.cpp}
412
 *
413
 *  MyDataset::~MyDataset()
414
 *  {
415
 *     try
416
 *     {
417
 *         MyDataset::Close();
418
 *     }
419
 *     catch (const std::exception &exc)
420
 *     {
421
 *         // If Close() can throw exception
422
 *         CPLError(CE_Failure, CPLE_AppDefined,
423
 *                  "Exception thrown in MyDataset::Close(): %s",
424
 *                  exc.what());
425
 *     }
426
 *     catch (...)
427
 *     {
428
 *         // If Close() can throw exception
429
 *         CPLError(CE_Failure, CPLE_AppDefined,
430
 *                  "Exception thrown in MyDataset::Close()");
431
 *     }
432
 *  }
433
 *
434
 *  CPLErr MyDataset::Close()
435
 *  {
436
 *      CPLErr eErr = CE_None;
437
 *      if( nOpenFlags != OPEN_FLAGS_CLOSED )
438
 *      {
439
 *          if( MyDataset::FlushCache(true) != CE_None )
440
 *              eErr = CE_Failure;
441
 *
442
 *          // Do something driver specific
443
 *          if (m_fpImage)
444
 *          {
445
 *              if( VSIFCloseL(m_fpImage) != 0 )
446
 *              {
447
 *                  CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
448
 *                  eErr = CE_Failure;
449
 *              }
450
 *          }
451
 *
452
 *          // Call parent Close() implementation.
453
 *          if( MyParentDatasetClass::Close() != CE_None )
454
 *              eErr = CE_Failure;
455
 *      }
456
 *      return eErr;
457
 *  }
458
 * \endcode
459
 *
460
 * @since GDAL 3.7
461
 */
462
CPLErr GDALDataset::Close()
463
0
{
464
    // Call UnregisterFromSharedDataset() before altering nOpenFlags
465
0
    UnregisterFromSharedDataset();
466
467
0
    nOpenFlags = OPEN_FLAGS_CLOSED;
468
0
    return CE_None;
469
0
}
470
471
/************************************************************************/
472
/*                UnregisterFromSharedDataset()                         */
473
/************************************************************************/
474
475
void GDALDataset::UnregisterFromSharedDataset()
476
0
{
477
0
    if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
478
0
        return;
479
480
0
    CPLMutexHolderD(&hDLMutex);
481
482
0
    std::map<GDALDataset *, GIntBig>::iterator oIter =
483
0
        poAllDatasetMap->find(this);
484
0
    CPLAssert(oIter != poAllDatasetMap->end());
485
0
    const GIntBig nPIDCreatorForShared = oIter->second;
486
0
    bShared = false;
487
0
    SharedDatasetCtxt sStruct;
488
0
    sStruct.nPID = nPIDCreatorForShared;
489
0
    sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
490
0
    sStruct.pszDescription = const_cast<char *>(GetDescription());
491
0
    std::string osConcatenatedOpenOptions =
492
0
        GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
493
0
    sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
494
0
    sStruct.poDS = nullptr;
495
0
    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
496
0
        CPLHashSetLookup(phSharedDatasetSet, &sStruct));
497
0
    if (psStruct && psStruct->poDS == this)
498
0
    {
499
0
        CPLHashSetRemove(phSharedDatasetSet, psStruct);
500
0
    }
501
0
    else
502
0
    {
503
0
        CPLDebug("GDAL",
504
0
                 "Should not happen. Cannot find %s, "
505
0
                 "this=%p in phSharedDatasetSet",
506
0
                 GetDescription(), this);
507
0
    }
508
0
}
509
510
/************************************************************************/
511
/*                      AddToDatasetOpenList()                          */
512
/************************************************************************/
513
514
void GDALDataset::AddToDatasetOpenList()
515
0
{
516
    /* -------------------------------------------------------------------- */
517
    /*      Add this dataset to the open dataset list.                      */
518
    /* -------------------------------------------------------------------- */
519
0
    bIsInternal = false;
520
521
0
    CPLMutexHolderD(&hDLMutex);
522
523
0
    if (poAllDatasetMap == nullptr)
524
0
        poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
525
0
    (*poAllDatasetMap)[this] = -1;
526
0
}
527
528
/************************************************************************/
529
/*                             FlushCache()                             */
530
/************************************************************************/
531
532
/**
533
 * \brief Flush all write cached data to disk.
534
 *
535
 * Any raster (or other GDAL) data written via GDAL calls, but buffered
536
 * internally will be written to disk.
537
 *
538
 * The default implementation of this method just calls the FlushCache() method
539
 * on each of the raster bands and the SyncToDisk() method
540
 * on each of the layers.  Conceptually, calling FlushCache() on a dataset
541
 * should include any work that might be accomplished by calling SyncToDisk()
542
 * on layers in that dataset.
543
 *
544
 * Using this method does not prevent use from calling GDALClose()
545
 * to properly close a dataset and ensure that important data not addressed
546
 * by FlushCache() is written in the file.
547
 *
548
 * This method is the same as the C function GDALFlushCache().
549
 *
550
 * @param bAtClosing Whether this is called from a GDALDataset destructor
551
 * @return CE_None in case of success (note: return value added in GDAL 3.7)
552
 */
553
554
CPLErr GDALDataset::FlushCache(bool bAtClosing)
555
556
0
{
557
0
    CPLErr eErr = CE_None;
558
    // This sometimes happens if a dataset is destroyed before completely
559
    // built.
560
561
0
    if (papoBands)
562
0
    {
563
0
        for (int i = 0; i < nBands; ++i)
564
0
        {
565
0
            if (papoBands[i])
566
0
            {
567
0
                if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
568
0
                    eErr = CE_Failure;
569
0
            }
570
0
        }
571
0
    }
572
573
0
    const int nLayers = GetLayerCount();
574
    // cppcheck-suppress knownConditionTrueFalse
575
0
    if (nLayers > 0)
576
0
    {
577
0
        CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
578
0
        for (int i = 0; i < nLayers; ++i)
579
0
        {
580
0
            OGRLayer *poLayer = GetLayer(i);
581
582
0
            if (poLayer)
583
0
            {
584
0
                if (poLayer->SyncToDisk() != OGRERR_NONE)
585
0
                    eErr = CE_Failure;
586
0
            }
587
0
        }
588
0
    }
589
590
0
    return eErr;
591
0
}
592
593
/************************************************************************/
594
/*                           GDALFlushCache()                           */
595
/************************************************************************/
596
597
/**
598
 * \brief Flush all write cached data to disk.
599
 *
600
 * @see GDALDataset::FlushCache().
601
 * @return CE_None in case of success (note: return value added in GDAL 3.7)
602
 */
603
604
CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
605
606
0
{
607
0
    VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
608
609
0
    return GDALDataset::FromHandle(hDS)->FlushCache(false);
610
0
}
611
612
/************************************************************************/
613
/*                             DropCache()                              */
614
/************************************************************************/
615
616
/**
617
* \brief Drop all write cached data
618
*
619
* This method is the same as the C function GDALDropCache().
620
*
621
* @return CE_None in case of success
622
* @since 3.9
623
*/
624
625
CPLErr GDALDataset::DropCache()
626
627
0
{
628
0
    CPLErr eErr = CE_None;
629
630
0
    if (papoBands)
631
0
    {
632
0
        for (int i = 0; i < nBands; ++i)
633
0
        {
634
0
            if (papoBands[i])
635
0
            {
636
0
                if (papoBands[i]->DropCache() != CE_None)
637
0
                    eErr = CE_Failure;
638
0
            }
639
0
        }
640
0
    }
641
642
0
    return eErr;
643
0
}
644
645
/************************************************************************/
646
/*                           GDALDropCache()                           */
647
/************************************************************************/
648
649
/**
650
* \brief Drop all write cached data
651
*
652
* @see GDALDataset::DropCache().
653
* @return CE_None in case of success
654
* @since 3.9
655
*/
656
657
CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
658
659
0
{
660
0
    VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
661
662
0
    return GDALDataset::FromHandle(hDS)->DropCache();
663
0
}
664
665
/************************************************************************/
666
/*                      GetEstimatedRAMUsage()                          */
667
/************************************************************************/
668
669
/**
670
 * \brief Return the intrinsic RAM usage of this dataset.
671
 *
672
 * The returned value should take into account caches in the underlying driver
673
 * and decoding library, but not the usage related to the GDAL block cache.
674
 *
675
 * At time of writing, this method is only implemented in the JP2OpenJPEG
676
 * driver. For single-tiled JPEG2000 images, the decoding of the image,
677
 * even partially, involves allocating at least
678
 * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
679
 * library.
680
 *
681
 * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
682
 * driver, to determine how long a dataset in the pool must be kept open, given
683
 * the RAM usage of the dataset with respect to the usable total RAM.
684
 *
685
 * @since GDAL 3.7
686
 * @return RAM usage in bytes, or -1 if unknown (the default implementation
687
 * returns -1)
688
 */
689
690
GIntBig GDALDataset::GetEstimatedRAMUsage()
691
0
{
692
0
    return -1;
693
0
}
694
695
/************************************************************************/
696
/*                        BlockBasedFlushCache()                        */
697
/*                                                                      */
698
/*      This helper method can be called by the                         */
699
/*      GDALDataset::FlushCache() for particular drivers to ensure      */
700
/*      that buffers will be flushed in a manner suitable for pixel     */
701
/*      interleaved (by block) IO.  That is, if all the bands have      */
702
/*      the same size blocks then a given block will be flushed for     */
703
/*      all bands before proceeding to the next block.                  */
704
/************************************************************************/
705
706
//! @cond Doxygen_Suppress
707
CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
708
709
0
{
710
0
    GDALRasterBand *poBand1 = GetRasterBand(1);
711
0
    if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
712
0
    {
713
0
        return GDALDataset::FlushCache(bAtClosing);
714
0
    }
715
716
0
    int nBlockXSize = 0;
717
0
    int nBlockYSize = 0;
718
0
    poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
719
720
    /* -------------------------------------------------------------------- */
721
    /*      Verify that all bands match.                                    */
722
    /* -------------------------------------------------------------------- */
723
0
    for (int iBand = 1; iBand < nBands; ++iBand)
724
0
    {
725
0
        GDALRasterBand *poBand = GetRasterBand(iBand + 1);
726
727
0
        int nThisBlockXSize, nThisBlockYSize;
728
0
        poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
729
0
        if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
730
0
        {
731
0
            return GDALDataset::FlushCache(bAtClosing);
732
0
        }
733
0
    }
734
735
    /* -------------------------------------------------------------------- */
736
    /*      Now flush writable data.                                        */
737
    /* -------------------------------------------------------------------- */
738
0
    for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
739
0
    {
740
0
        for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
741
0
        {
742
0
            for (int iBand = 0; iBand < nBands; ++iBand)
743
0
            {
744
0
                const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);
745
746
0
                if (eErr != CE_None)
747
0
                    return CE_Failure;
748
0
            }
749
0
        }
750
0
    }
751
0
    return CE_None;
752
0
}
753
754
/************************************************************************/
755
/*                          RasterInitialize()                          */
756
/*                                                                      */
757
/*      Initialize raster size                                          */
758
/************************************************************************/
759
760
void GDALDataset::RasterInitialize(int nXSize, int nYSize)
761
762
0
{
763
0
    CPLAssert(nXSize > 0 && nYSize > 0);
764
765
0
    nRasterXSize = nXSize;
766
0
    nRasterYSize = nYSize;
767
0
}
768
769
//! @endcond
770
771
/************************************************************************/
772
/*                              AddBand()                               */
773
/************************************************************************/
774
775
/**
776
 * \fn GDALDataset::AddBand(GDALDataType, char**)
777
 * \brief Add a band to a dataset.
778
 *
779
 * This method will add a new band to the dataset if the underlying format
780
 * supports this action.  Most formats do not.
781
 *
782
 * Note that the new GDALRasterBand is not returned.  It may be fetched
783
 * after successful completion of the method by calling
784
 * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
785
 * band will always be the last band.
786
 *
787
 * @param eType the data type of the pixels in the new band.
788
 *
789
 * @param papszOptions a list of NAME=VALUE option strings.  The supported
790
 * options are format specific.  NULL may be passed by default.
791
 *
792
 * @return CE_None on success or CE_Failure on failure.
793
 */
794
795
CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
796
                            CPL_UNUSED char **papszOptions)
797
798
0
{
799
0
    ReportError(CE_Failure, CPLE_NotSupported,
800
0
                "Dataset does not support the AddBand() method.");
801
802
0
    return CE_Failure;
803
0
}
804
805
/************************************************************************/
806
/*                            GDALAddBand()                             */
807
/************************************************************************/
808
809
/**
810
 * \brief Add a band to a dataset.
811
 *
812
 * @see GDALDataset::AddBand().
813
 */
814
815
CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
816
                               CSLConstList papszOptions)
817
818
0
{
819
0
    VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
820
821
0
    return GDALDataset::FromHandle(hDataset)->AddBand(
822
0
        eType, const_cast<char **>(papszOptions));
823
0
}
824
825
/************************************************************************/
826
/*                              SetBand()                               */
827
/************************************************************************/
828
829
//! @cond Doxygen_Suppress
830
/**  Set a band in the band array, updating the band count, and array size
831
 * appropriately.
832
 *
833
 * @param nNewBand new band number (indexing starts at 1)
834
 * @param poBand band object.
835
 */
836
837
void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
838
839
0
{
840
    /* -------------------------------------------------------------------- */
841
    /*      Do we need to grow the bands list?                              */
842
    /* -------------------------------------------------------------------- */
843
0
    if (nBands < nNewBand || papoBands == nullptr)
844
0
    {
845
0
        GDALRasterBand **papoNewBands = nullptr;
846
847
0
        if (papoBands == nullptr)
848
0
            papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
849
0
                sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
850
0
        else
851
0
            papoNewBands = static_cast<GDALRasterBand **>(
852
0
                VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
853
0
                                          std::max(nNewBand, nBands)));
854
0
        if (papoNewBands == nullptr)
855
0
        {
856
0
            ReportError(CE_Failure, CPLE_OutOfMemory,
857
0
                        "Cannot allocate band array");
858
0
            return;
859
0
        }
860
861
0
        papoBands = papoNewBands;
862
863
0
        for (int i = nBands; i < nNewBand; ++i)
864
0
            papoBands[i] = nullptr;
865
866
0
        nBands = std::max(nBands, nNewBand);
867
868
0
        if (m_poPrivate)
869
0
        {
870
0
            for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
871
0
                 i < nBands; ++i)
872
0
            {
873
0
                m_poPrivate->m_anBandMap.push_back(i + 1);
874
0
            }
875
0
        }
876
0
    }
877
878
    /* -------------------------------------------------------------------- */
879
    /*      Set the band.  Resetting the band is currently not permitted.   */
880
    /* -------------------------------------------------------------------- */
881
0
    if (papoBands[nNewBand - 1] != nullptr)
882
0
    {
883
0
        ReportError(CE_Failure, CPLE_NotSupported,
884
0
                    "Cannot set band %d as it is already set", nNewBand);
885
0
        return;
886
0
    }
887
888
0
    papoBands[nNewBand - 1] = poBand;
889
890
    /* -------------------------------------------------------------------- */
891
    /*      Set back reference information on the raster band.  Note        */
892
    /*      that the GDALDataset is a friend of the GDALRasterBand          */
893
    /*      specifically to allow this.                                     */
894
    /* -------------------------------------------------------------------- */
895
0
    poBand->nBand = nNewBand;
896
0
    poBand->poDS = this;
897
0
    poBand->nRasterXSize = nRasterXSize;
898
0
    poBand->nRasterYSize = nRasterYSize;
899
0
    poBand->eAccess = eAccess;  // Default access to be same as dataset.
900
0
}
901
902
//! @endcond
903
904
/************************************************************************/
905
/*                              SetBand()                               */
906
/************************************************************************/
907
908
//! @cond Doxygen_Suppress
909
/**  Set a band in the band array, updating the band count, and array size
910
 * appropriately.
911
 *
912
 * @param nNewBand new band number (indexing starts at 1)
913
 * @param poBand band object.
914
 */
915
916
void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
917
0
{
918
0
    SetBand(nNewBand, poBand.release());
919
0
}
920
921
//! @endcond
922
923
/************************************************************************/
924
/*                           GetRasterXSize()                           */
925
/************************************************************************/
926
927
/**
928
929
 \brief Fetch raster width in pixels.
930
931
 Equivalent of the C function GDALGetRasterXSize().
932
933
 @return the width in pixels of raster bands in this GDALDataset.
934
935
*/
936
937
int GDALDataset::GetRasterXSize() const
938
0
{
939
0
    return nRasterXSize;
940
0
}
941
942
/************************************************************************/
943
/*                         GDALGetRasterXSize()                         */
944
/************************************************************************/
945
946
/**
947
 * \brief Fetch raster width in pixels.
948
 *
949
 * @see GDALDataset::GetRasterXSize().
950
 */
951
952
int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
953
954
0
{
955
0
    VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
956
957
0
    return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
958
0
}
959
960
/************************************************************************/
961
/*                           GetRasterYSize()                           */
962
/************************************************************************/
963
964
/**
965
966
 \brief Fetch raster height in pixels.
967
968
 Equivalent of the C function GDALGetRasterYSize().
969
970
 @return the height in pixels of raster bands in this GDALDataset.
971
972
*/
973
974
int GDALDataset::GetRasterYSize() const
975
0
{
976
0
    return nRasterYSize;
977
0
}
978
979
/************************************************************************/
980
/*                         GDALGetRasterYSize()                         */
981
/************************************************************************/
982
983
/**
984
 * \brief Fetch raster height in pixels.
985
 *
986
 * @see GDALDataset::GetRasterYSize().
987
 */
988
989
int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
990
991
0
{
992
0
    VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
993
994
0
    return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
995
0
}
996
997
/************************************************************************/
998
/*                           GetRasterBand()                            */
999
/************************************************************************/
1000
1001
/**
1002
1003
 \brief Fetch a band object for a dataset.
1004
1005
 See GetBands() for a C++ iterator version of this method.
1006
1007
 Equivalent of the C function GDALGetRasterBand().
1008
1009
 @param nBandId the index number of the band to fetch, from 1 to
1010
                GetRasterCount().
1011
1012
 @return the nBandId th band object
1013
1014
*/
1015
1016
GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1017
1018
0
{
1019
0
    if (papoBands)
1020
0
    {
1021
0
        if (nBandId < 1 || nBandId > nBands)
1022
0
        {
1023
0
            ReportError(CE_Failure, CPLE_IllegalArg,
1024
0
                        "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1025
0
                        nBandId);
1026
0
            return nullptr;
1027
0
        }
1028
1029
0
        return papoBands[nBandId - 1];
1030
0
    }
1031
0
    return nullptr;
1032
0
}
1033
1034
/************************************************************************/
1035
/*                           GetRasterBand()                            */
1036
/************************************************************************/
1037
1038
/**
1039
1040
 \brief Fetch a band object for a dataset.
1041
1042
 See GetBands() for a C++ iterator version of this method.
1043
1044
 Equivalent of the C function GDALGetRasterBand().
1045
1046
 @param nBandId the index number of the band to fetch, from 1 to
1047
                GetRasterCount().
1048
1049
 @return the nBandId th band object
1050
1051
*/
1052
1053
const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1054
1055
0
{
1056
0
    if (papoBands)
1057
0
    {
1058
0
        if (nBandId < 1 || nBandId > nBands)
1059
0
        {
1060
0
            ReportError(CE_Failure, CPLE_IllegalArg,
1061
0
                        "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1062
0
                        nBandId);
1063
0
            return nullptr;
1064
0
        }
1065
1066
0
        return papoBands[nBandId - 1];
1067
0
    }
1068
0
    return nullptr;
1069
0
}
1070
1071
/************************************************************************/
1072
/*                         GDALGetRasterBand()                          */
1073
/************************************************************************/
1074
1075
/**
1076
 * \brief Fetch a band object for a dataset.
1077
 * @see GDALDataset::GetRasterBand().
1078
 */
1079
1080
GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1081
1082
0
{
1083
0
    VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1084
1085
0
    return GDALRasterBand::ToHandle(
1086
0
        GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
1087
0
}
1088
1089
/************************************************************************/
1090
/*                           GetRasterCount()                           */
1091
/************************************************************************/
1092
1093
/**
1094
 * \brief Fetch the number of raster bands on this dataset.
1095
 *
1096
 * Same as the C function GDALGetRasterCount().
1097
 *
1098
 * @return the number of raster bands.
1099
 */
1100
1101
int GDALDataset::GetRasterCount() const
1102
0
{
1103
0
    return papoBands ? nBands : 0;
1104
0
}
1105
1106
/************************************************************************/
1107
/*                         GDALGetRasterCount()                         */
1108
/************************************************************************/
1109
1110
/**
1111
 * \brief Fetch the number of raster bands on this dataset.
1112
 *
1113
 * @see GDALDataset::GetRasterCount().
1114
 */
1115
1116
int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1117
1118
0
{
1119
0
    VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1120
1121
0
    return GDALDataset::FromHandle(hDS)->GetRasterCount();
1122
0
}
1123
1124
/************************************************************************/
1125
/*                          GetProjectionRef()                          */
1126
/************************************************************************/
1127
1128
/**
1129
 * \brief Fetch the projection definition string for this dataset.
1130
 *
1131
 * Same as the C function GDALGetProjectionRef().
1132
 *
1133
 * The returned string defines the projection coordinate system of the
1134
 * image in OpenGIS WKT format.  It should be suitable for use with the
1135
 * OGRSpatialReference class.
1136
 *
1137
 * When a projection definition is not available an empty (but not NULL)
1138
 * string is returned.
1139
 *
1140
 * \note Starting with GDAL 3.0, this is a compatibility layer around
1141
 * GetSpatialRef()
1142
 *
1143
 * @return a pointer to an internal projection reference string.  It should
1144
 * not be altered, freed or expected to last for long.
1145
 *
1146
 * @see https://gdal.org/tutorials/osr_api_tut.html
1147
 */
1148
1149
const char *GDALDataset::GetProjectionRef() const
1150
0
{
1151
0
    const auto poSRS = GetSpatialRef();
1152
0
    if (!poSRS || !m_poPrivate)
1153
0
    {
1154
0
        return "";
1155
0
    }
1156
0
    char *pszWKT = nullptr;
1157
0
    poSRS->exportToWkt(&pszWKT);
1158
0
    if (!pszWKT)
1159
0
    {
1160
0
        return "";
1161
0
    }
1162
1163
    // If called on a thread-safe dataset, we might be called by several
1164
    // threads, so make sure our accesses to m_pszWKTCached are protected
1165
    // by a mutex.
1166
0
    std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1167
0
    if (m_poPrivate->m_pszWKTCached &&
1168
0
        strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1169
0
    {
1170
0
        CPLFree(pszWKT);
1171
0
        return m_poPrivate->m_pszWKTCached;
1172
0
    }
1173
0
    CPLFree(m_poPrivate->m_pszWKTCached);
1174
0
    m_poPrivate->m_pszWKTCached = pszWKT;
1175
0
    return m_poPrivate->m_pszWKTCached;
1176
0
}
1177
1178
/************************************************************************/
1179
/*                           GetSpatialRef()                            */
1180
/************************************************************************/
1181
1182
/**
1183
 * \brief Fetch the spatial reference for this dataset.
1184
 *
1185
 * Same as the C function GDALGetSpatialRef().
1186
 *
1187
 * When a projection definition is not available, null is returned. If used on
1188
 * a dataset where there are GCPs and not a geotransform, this method returns
1189
 * null. Use GetGCPSpatialRef() instead.
1190
 *
1191
 * @since GDAL 3.0
1192
 *
1193
 * @return a pointer to an internal object. It should not be altered or freed.
1194
 * Its lifetime will be the one of the dataset object, or until the next
1195
 * call to this method.
1196
 *
1197
 * @see https://gdal.org/tutorials/osr_api_tut.html
1198
 */
1199
1200
const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1201
0
{
1202
0
    return nullptr;
1203
0
}
1204
1205
/************************************************************************/
1206
/*                        GDALGetSpatialRef()                           */
1207
/************************************************************************/
1208
1209
/**
1210
 * \brief Fetch the spatial reference for this dataset.
1211
 *
1212
 * @since GDAL 3.0
1213
 *
1214
 * @see GDALDataset::GetSpatialRef()
1215
 */
1216
1217
OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1218
1219
0
{
1220
0
    VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1221
1222
0
    return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1223
0
        GDALDataset::FromHandle(hDS)->GetSpatialRef()));
1224
0
}
1225
1226
/************************************************************************/
1227
/*                        GDALGetProjectionRef()                        */
1228
/************************************************************************/
1229
1230
/**
1231
 * \brief Fetch the projection definition string for this dataset.
1232
 *
1233
 * @see GDALDataset::GetProjectionRef()
1234
 */
1235
1236
const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1237
1238
0
{
1239
0
    VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1240
1241
0
    return GDALDataset::FromHandle(hDS)->GetProjectionRef();
1242
0
}
1243
1244
/************************************************************************/
1245
/*                           SetProjection()                            */
1246
/************************************************************************/
1247
1248
/**
1249
 * \brief Set the projection reference string for this dataset.
1250
 *
1251
 * The string should be in OGC WKT or PROJ.4 format.  An error may occur
1252
 * because of incorrectly specified projection strings, because the dataset
1253
 * is not writable, or because the dataset does not support the indicated
1254
 * projection.  Many formats do not support writing projections.
1255
 *
1256
 * This method is the same as the C GDALSetProjection() function.
1257
 *
1258
 * \note Startig with GDAL 3.0, this is a compatibility layer around
1259
 * SetSpatialRef()
1260
1261
 * @param pszProjection projection reference string.
1262
 *
1263
 * @return CE_Failure if an error occurs, otherwise CE_None.
1264
 */
1265
1266
CPLErr GDALDataset::SetProjection(const char *pszProjection)
1267
0
{
1268
0
    if (pszProjection && pszProjection[0] != '\0')
1269
0
    {
1270
0
        OGRSpatialReference oSRS;
1271
0
        oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1272
0
        if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1273
0
        {
1274
0
            return CE_Failure;
1275
0
        }
1276
0
        return SetSpatialRef(&oSRS);
1277
0
    }
1278
0
    else
1279
0
    {
1280
0
        return SetSpatialRef(nullptr);
1281
0
    }
1282
0
}
1283
1284
/************************************************************************/
1285
/*                           SetSpatialRef()                            */
1286
/************************************************************************/
1287
1288
/**
1289
 * \brief Set the spatial reference system for this dataset.
1290
 *
1291
 * An error may occur because the dataset
1292
 * is not writable, or because the dataset does not support the indicated
1293
 * projection. Many formats do not support writing projections.
1294
 *
1295
 * This method is the same as the C GDALSetSpatialRef() function.
1296
 *
1297
 * @since GDAL 3.0
1298
1299
 * @param poSRS spatial reference system object. nullptr can potentially be
1300
 * passed for drivers that support unsetting the SRS.
1301
 *
1302
 * @return CE_Failure if an error occurs, otherwise CE_None.
1303
 */
1304
1305
CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
1306
0
{
1307
0
    if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1308
0
        ReportError(CE_Failure, CPLE_NotSupported,
1309
0
                    "Dataset does not support the SetSpatialRef() method.");
1310
0
    return CE_Failure;
1311
0
}
1312
1313
/************************************************************************/
1314
/*                         GDALSetSpatialRef()                          */
1315
/************************************************************************/
1316
1317
/**
1318
 * \brief Set the spatial reference system for this dataset.
1319
 *
1320
 * @since GDAL 3.0
1321
 *
1322
 * @see GDALDataset::SetSpatialRef()
1323
 */
1324
1325
CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1326
1327
0
{
1328
0
    VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1329
1330
0
    return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1331
0
        OGRSpatialReference::FromHandle(hSRS));
1332
0
}
1333
1334
/************************************************************************/
1335
/*                         GDALSetProjection()                          */
1336
/************************************************************************/
1337
1338
/**
1339
 * \brief Set the projection reference string for this dataset.
1340
 *
1341
 * @see GDALDataset::SetProjection()
1342
 */
1343
1344
CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1345
                                     const char *pszProjection)
1346
1347
0
{
1348
0
    VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1349
1350
0
    return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1351
0
}
1352
1353
/************************************************************************/
1354
/*                          GetGeoTransform()                           */
1355
/************************************************************************/
1356
1357
/**
1358
 * \brief Fetch the affine transformation coefficients.
1359
 *
1360
 * Fetches the coefficients for transforming between pixel/line (P,L) raster
1361
 * space, and projection coordinates (Xp,Yp) space.
1362
 *
1363
 * \code
1364
 *   Xp = gt[0] + P*gt[1] + L*gt[2];
1365
 *   Yp = gt[3] + P*padfTransform[4] + L*gt[5];
1366
 * \endcode
1367
 *
1368
 * In a north up image, gt[1] is the pixel width, and
1369
 * gt[5] is the pixel height.  The upper left corner of the
1370
 * upper left pixel is at position (gt[0],gt[3]).
1371
 *
1372
 * The default transform is (0,1,0,0,0,1) and should be returned even when
1373
 * a CE_Failure error is returned, such as for formats that don't support
1374
 * transformation to projection coordinates.
1375
 *
1376
 * This method does the same thing as the C GDALGetGeoTransform() function.
1377
 *
1378
 * @param gt an existing six double buffer into which the
1379
 * transformation will be placed.
1380
 *
1381
 * @return CE_None on success, or CE_Failure if no transform can be fetched.
1382
 *
1383
 * @since 3.12
1384
 */
1385
1386
CPLErr GDALDataset::GetGeoTransform(GDALGeoTransform &gt) const
1387
1388
0
{
1389
0
    gt = GDALGeoTransform();
1390
1391
0
    return CE_Failure;
1392
0
}
1393
1394
/************************************************************************/
1395
/*                          GetGeoTransform()                           */
1396
/************************************************************************/
1397
1398
/**
1399
 * \brief Fetch the affine transformation coefficients.
1400
 *
1401
 * Fetches the coefficients for transforming between pixel/line (P,L) raster
1402
 * space, and projection coordinates (Xp,Yp) space.
1403
 *
1404
 * \code
1405
 *   Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1406
 *   Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1407
 * \endcode
1408
 *
1409
 * In a north up image, padfTransform[1] is the pixel width, and
1410
 * padfTransform[5] is the pixel height.  The upper left corner of the
1411
 * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1412
 *
1413
 * The default transform is (0,1,0,0,0,1) and should be returned even when
1414
 * a CE_Failure error is returned, such as for formats that don't support
1415
 * transformation to projection coordinates.
1416
 *
1417
 * This method does the same thing as the C GDALGetGeoTransform() function.
1418
 *
1419
 * @param padfTransform an existing six double buffer into which the
1420
 * transformation will be placed.
1421
 *
1422
 * @return CE_None on success, or CE_Failure if no transform can be fetched.
1423
 *
1424
 * @deprecated since 3.12. Use GetGeoTransform(GDALGeoTransform&) instead
1425
 */
1426
1427
CPLErr GDALDataset::GetGeoTransform(double *padfTransform) const
1428
1429
0
{
1430
0
    return GetGeoTransform(
1431
0
        *reinterpret_cast<GDALGeoTransform *>(padfTransform));
1432
0
}
1433
1434
/************************************************************************/
1435
/*                        GDALGetGeoTransform()                         */
1436
/************************************************************************/
1437
1438
/**
1439
 * \brief Fetch the affine transformation coefficients.
1440
 *
1441
 * @see GDALDataset::GetGeoTransform()
1442
 */
1443
1444
CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1445
1446
0
{
1447
0
    VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1448
1449
0
    return GDALDataset::FromHandle(hDS)->GetGeoTransform(
1450
0
        *reinterpret_cast<GDALGeoTransform *>(padfTransform));
1451
0
}
1452
1453
/************************************************************************/
1454
/*                          SetGeoTransform()                           */
1455
/************************************************************************/
1456
1457
/**
1458
 * \fn GDALDataset::SetGeoTransform(const GDALGeoTransform&)
1459
 * \brief Set the affine transformation coefficients.
1460
 *
1461
 * See GetGeoTransform() for details on the meaning of the padfTransform
1462
 * coefficients.
1463
 *
1464
 * This method does the same thing as the C GDALSetGeoTransform() function.
1465
 *
1466
 * @param gt the transformation coefficients to be written with the dataset.
1467
 *
1468
 * @return CE_None on success, or CE_Failure if this transform cannot be
1469
 * written.
1470
 *
1471
 * @since 3.12
1472
 */
1473
1474
CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED const GDALGeoTransform &gt)
1475
1476
0
{
1477
0
    if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1478
0
        ReportError(CE_Failure, CPLE_NotSupported,
1479
0
                    "SetGeoTransform() not supported for this dataset.");
1480
1481
0
    return CE_Failure;
1482
0
}
1483
1484
/************************************************************************/
1485
/*                          SetGeoTransform()                           */
1486
/************************************************************************/
1487
1488
/**
1489
 * \brief Set the affine transformation coefficients.
1490
 *
1491
 * See GetGeoTransform() for details on the meaning of the padfTransform
1492
 * coefficients.
1493
 *
1494
 * This method does the same thing as the C GDALSetGeoTransform() function.
1495
 *
1496
 * @param padfTransform a six double buffer containing the transformation
1497
 * coefficients to be written with the dataset.
1498
 *
1499
 * @return CE_None on success, or CE_Failure if this transform cannot be
1500
 * written.
1501
 *
1502
 * @deprecated since 3.12. Use SetGeoTransform(const GDALGeoTransform&) instead
1503
 */
1504
CPLErr GDALDataset::SetGeoTransform(const double *padfTransform)
1505
1506
0
{
1507
0
    return SetGeoTransform(
1508
0
        *reinterpret_cast<const GDALGeoTransform *>(padfTransform));
1509
0
}
1510
1511
/************************************************************************/
1512
/*                        GDALSetGeoTransform()                         */
1513
/************************************************************************/
1514
1515
/**
1516
 * \brief Set the affine transformation coefficients.
1517
 *
1518
 * @see GDALDataset::SetGeoTransform()
1519
 */
1520
1521
CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS,
1522
                                       const double *padfTransform)
1523
1524
0
{
1525
0
    VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1526
0
    VALIDATE_POINTER1(padfTransform, "GDALSetGeoTransform", CE_Failure);
1527
1528
0
    return GDALDataset::FromHandle(hDS)->SetGeoTransform(
1529
0
        *reinterpret_cast<const GDALGeoTransform *>(padfTransform));
1530
0
}
1531
1532
/************************************************************************/
1533
/*                         GetInternalHandle()                          */
1534
/************************************************************************/
1535
1536
/**
1537
 * \fn GDALDataset::GetInternalHandle(const char*)
1538
 * \brief Fetch a format specific internally meaningful handle.
1539
 *
1540
 * This method is the same as the C GDALGetInternalHandle() method.
1541
 *
1542
 * @param pszHandleName the handle name desired.  The meaningful names
1543
 * will be specific to the file format.
1544
 *
1545
 * @return the desired handle value, or NULL if not recognized/supported.
1546
 */
1547
1548
void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
1549
1550
0
{
1551
0
    return nullptr;
1552
0
}
1553
1554
/************************************************************************/
1555
/*                       GDALGetInternalHandle()                        */
1556
/************************************************************************/
1557
1558
/**
1559
 * \brief Fetch a format specific internally meaningful handle.
1560
 *
1561
 * @see GDALDataset::GetInternalHandle()
1562
 */
1563
1564
void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
1565
                                        const char *pszRequest)
1566
1567
0
{
1568
0
    VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1569
1570
0
    return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1571
0
}
1572
1573
/************************************************************************/
1574
/*                             GetDriver()                              */
1575
/************************************************************************/
1576
1577
/**
1578
 * \brief Fetch the driver to which this dataset relates.
1579
 *
1580
 * This method is the same as the C GDALGetDatasetDriver() function.
1581
 *
1582
 * @return the driver on which the dataset was created with GDALOpen() or
1583
 * GDALCreate().
1584
 */
1585
1586
GDALDriver *GDALDataset::GetDriver()
1587
0
{
1588
0
    return poDriver;
1589
0
}
1590
1591
/************************************************************************/
1592
/*                        GDALGetDatasetDriver()                        */
1593
/************************************************************************/
1594
1595
/**
1596
 * \brief Fetch the driver to which this dataset relates.
1597
 *
1598
 * @see GDALDataset::GetDriver()
1599
 */
1600
1601
GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1602
1603
0
{
1604
0
    VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1605
1606
0
    return static_cast<GDALDriverH>(
1607
0
        GDALDataset::FromHandle(hDataset)->GetDriver());
1608
0
}
1609
1610
/************************************************************************/
1611
/*                             Reference()                              */
1612
/************************************************************************/
1613
1614
/**
1615
 * \brief Add one to dataset reference count.
1616
 *
1617
 * The reference is one after instantiation.
1618
 *
1619
 * This method is the same as the C GDALReferenceDataset() function.
1620
 *
1621
 * @return the post-increment reference count.
1622
 */
1623
1624
int GDALDataset::Reference()
1625
0
{
1626
0
    return ++nRefCount;
1627
0
}
1628
1629
/************************************************************************/
1630
/*                        GDALReferenceDataset()                        */
1631
/************************************************************************/
1632
1633
/**
1634
 * \brief Add one to dataset reference count.
1635
 *
1636
 * @see GDALDataset::Reference()
1637
 */
1638
1639
int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1640
1641
0
{
1642
0
    VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1643
1644
0
    return GDALDataset::FromHandle(hDataset)->Reference();
1645
0
}
1646
1647
/************************************************************************/
1648
/*                            Dereference()                             */
1649
/************************************************************************/
1650
1651
/**
1652
 * \brief Subtract one from dataset reference count.
1653
 *
1654
 * The reference is one after instantiation.  Generally when the reference
1655
 * count has dropped to zero the dataset may be safely deleted (closed).
1656
 *
1657
 * This method is the same as the C GDALDereferenceDataset() function.
1658
 *
1659
 * @return the post-decrement reference count.
1660
 */
1661
1662
int GDALDataset::Dereference()
1663
0
{
1664
0
    return --nRefCount;
1665
0
}
1666
1667
/************************************************************************/
1668
/*                       GDALDereferenceDataset()                       */
1669
/************************************************************************/
1670
1671
/**
1672
 * \brief Subtract one from dataset reference count.
1673
 *
1674
 * @see GDALDataset::Dereference()
1675
 */
1676
1677
int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1678
1679
0
{
1680
0
    VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1681
1682
0
    return GDALDataset::FromHandle(hDataset)->Dereference();
1683
0
}
1684
1685
/************************************************************************/
1686
/*                            ReleaseRef()                              */
1687
/************************************************************************/
1688
1689
/**
1690
 * \brief Drop a reference to this object, and destroy if no longer referenced.
1691
 * @return TRUE if the object has been destroyed.
1692
 * @since GDAL 2.2
1693
 */
1694
1695
int GDALDataset::ReleaseRef()
1696
1697
0
{
1698
0
    if (Dereference() <= 0)
1699
0
    {
1700
0
        nRefCount = 1;
1701
0
        delete this;
1702
0
        return TRUE;
1703
0
    }
1704
0
    return FALSE;
1705
0
}
1706
1707
/************************************************************************/
1708
/*                        GDALReleaseDataset()                          */
1709
/************************************************************************/
1710
1711
/**
1712
 * \brief Drop a reference to this object, and destroy if no longer referenced.
1713
 *
1714
 * @see GDALDataset::ReleaseRef()
1715
 * @since GDAL 2.2
1716
 */
1717
1718
int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1719
1720
0
{
1721
0
    VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1722
1723
0
    return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1724
0
}
1725
1726
/************************************************************************/
1727
/*                             GetShared()                              */
1728
/************************************************************************/
1729
1730
/**
1731
 * \brief Returns shared flag.
1732
 *
1733
 * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1734
 */
1735
1736
int GDALDataset::GetShared() const
1737
0
{
1738
0
    return bShared;
1739
0
}
1740
1741
/************************************************************************/
1742
/*                            MarkAsShared()                            */
1743
/************************************************************************/
1744
1745
/**
1746
 * \brief Mark this dataset as available for sharing.
1747
 */
1748
1749
void GDALDataset::MarkAsShared()
1750
1751
0
{
1752
0
    CPLAssert(!bShared);
1753
1754
0
    bShared = true;
1755
0
    if (bIsInternal)
1756
0
        return;
1757
1758
0
    GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1759
1760
    // Insert the dataset in the set of shared opened datasets.
1761
0
    CPLMutexHolderD(&hDLMutex);
1762
0
    if (phSharedDatasetSet == nullptr)
1763
0
        phSharedDatasetSet =
1764
0
            CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1765
0
                          GDALSharedDatasetFreeFunc);
1766
1767
0
    SharedDatasetCtxt *psStruct =
1768
0
        static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1769
0
    psStruct->poDS = this;
1770
0
    psStruct->nPID = nPID;
1771
0
    psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1772
0
    psStruct->pszDescription = CPLStrdup(GetDescription());
1773
0
    std::string osConcatenatedOpenOptions =
1774
0
        GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1775
0
    psStruct->pszConcatenatedOpenOptions =
1776
0
        CPLStrdup(osConcatenatedOpenOptions.c_str());
1777
0
    if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1778
0
    {
1779
0
        GDALSharedDatasetFreeFunc(psStruct);
1780
0
        ReportError(CE_Failure, CPLE_AppDefined,
1781
0
                    "An existing shared dataset already has this description. "
1782
0
                    "This should not happen.");
1783
0
    }
1784
0
    else
1785
0
    {
1786
0
        CPLHashSetInsert(phSharedDatasetSet, psStruct);
1787
1788
0
        (*poAllDatasetMap)[this] = nPID;
1789
0
    }
1790
0
}
1791
1792
/************************************************************************/
1793
/*                        MarkSuppressOnClose()                         */
1794
/************************************************************************/
1795
1796
/** Set that the dataset must be deleted on close.
1797
 *
1798
 * This is the same as C function GDALDatasetMarkSuppressOnClose()
1799
 */
1800
void GDALDataset::MarkSuppressOnClose()
1801
0
{
1802
0
    bSuppressOnClose = true;
1803
0
}
1804
1805
/************************************************************************/
1806
/*                   GDALDatasetMarkSuppressOnClose()                   */
1807
/************************************************************************/
1808
1809
/** Set that the dataset must be deleted on close.
1810
 *
1811
 * This is the same as C++ method GDALDataset::MarkSuppressOnClose()
1812
 *
1813
 * @since GDAL 3.12
1814
 */
1815
1816
void GDALDatasetMarkSuppressOnClose(GDALDatasetH hDS)
1817
0
{
1818
0
    VALIDATE_POINTER0(hDS, "GDALDatasetMarkSuppressOnClose");
1819
1820
0
    return GDALDataset::FromHandle(hDS)->MarkSuppressOnClose();
1821
0
}
1822
1823
/************************************************************************/
1824
/*                       UnMarkSuppressOnClose()                        */
1825
/************************************************************************/
1826
1827
/** Remove the flag requesting the dataset to be deleted on close. */
1828
void GDALDataset::UnMarkSuppressOnClose()
1829
0
{
1830
0
    bSuppressOnClose = false;
1831
0
}
1832
1833
/************************************************************************/
1834
/*                        CleanupPostFileClosing()                      */
1835
/************************************************************************/
1836
1837
/** This method should be called by driver implementations in their destructor,
1838
 * after having closed all files, but before having freed resources that
1839
 * are needed for their GetFileList() implementation.
1840
 * This is used to implement MarkSuppressOnClose behavior.
1841
 */
1842
void GDALDataset::CleanupPostFileClosing()
1843
0
{
1844
0
    if (IsMarkedSuppressOnClose())
1845
0
    {
1846
0
        char **papszFileList = GetFileList();
1847
0
        for (int i = 0; papszFileList && papszFileList[i]; ++i)
1848
0
            VSIUnlink(papszFileList[i]);
1849
0
        CSLDestroy(papszFileList);
1850
0
    }
1851
0
}
1852
1853
/************************************************************************/
1854
/*                            GetGCPCount()                             */
1855
/************************************************************************/
1856
1857
/**
1858
 * \brief Get number of GCPs.
1859
 *
1860
 * This method is the same as the C function GDALGetGCPCount().
1861
 *
1862
 * @return number of GCPs for this dataset.  Zero if there are none.
1863
 */
1864
1865
int GDALDataset::GetGCPCount()
1866
0
{
1867
0
    return 0;
1868
0
}
1869
1870
/************************************************************************/
1871
/*                          GDALGetGCPCount()                           */
1872
/************************************************************************/
1873
1874
/**
1875
 * \brief Get number of GCPs.
1876
 *
1877
 * @see GDALDataset::GetGCPCount()
1878
 */
1879
1880
int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1881
1882
0
{
1883
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1884
1885
0
    return GDALDataset::FromHandle(hDS)->GetGCPCount();
1886
0
}
1887
1888
/************************************************************************/
1889
/*                          GetGCPProjection()                          */
1890
/************************************************************************/
1891
1892
/**
1893
 * \brief Get output projection for GCPs.
1894
 *
1895
 * This method is the same as the C function GDALGetGCPProjection().
1896
 *
1897
 * The projection string follows the normal rules from GetProjectionRef().
1898
 *
1899
 * \note Starting with GDAL 3.0, this is a compatibility layer around
1900
 * GetGCPSpatialRef()
1901
 *
1902
 * @return internal projection string or "" if there are no GCPs.
1903
 *  It should not be altered, freed or expected to last for long.
1904
 */
1905
1906
const char *GDALDataset::GetGCPProjection()
1907
0
{
1908
0
    const auto poSRS = GetGCPSpatialRef();
1909
0
    if (!poSRS || !m_poPrivate)
1910
0
    {
1911
0
        return "";
1912
0
    }
1913
0
    char *pszWKT = nullptr;
1914
0
    poSRS->exportToWkt(&pszWKT);
1915
0
    if (!pszWKT)
1916
0
    {
1917
0
        return "";
1918
0
    }
1919
1920
    // If called on a thread-safe dataset, we might be called by several
1921
    // threads, so make sure our accesses to m_pszWKTCached are protected
1922
    // by a mutex.
1923
0
    std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1924
0
    if (m_poPrivate->m_pszWKTGCPCached &&
1925
0
        strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
1926
0
    {
1927
0
        CPLFree(pszWKT);
1928
0
        return m_poPrivate->m_pszWKTGCPCached;
1929
0
    }
1930
0
    CPLFree(m_poPrivate->m_pszWKTGCPCached);
1931
0
    m_poPrivate->m_pszWKTGCPCached = pszWKT;
1932
0
    return m_poPrivate->m_pszWKTGCPCached;
1933
0
}
1934
1935
/************************************************************************/
1936
/*                          GetGCPSpatialRef()                          */
1937
/************************************************************************/
1938
1939
/**
1940
 * \brief Get output spatial reference system for GCPs.
1941
 *
1942
 * Same as the C function GDALGetGCPSpatialRef().
1943
 *
1944
 * When a SRS is not available, null is returned. If used on
1945
 * a dataset where there is a geotransform, and not GCPs, this method returns
1946
 * null. Use GetSpatialRef() instead.
1947
 *
1948
 * @since GDAL 3.0
1949
 *
1950
 * @return a pointer to an internal object. It should not be altered or freed.
1951
 * Its lifetime will be the one of the dataset object, or until the next
1952
 * call to this method.
1953
 */
1954
1955
const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
1956
0
{
1957
0
    return nullptr;
1958
0
}
1959
1960
/************************************************************************/
1961
/*                       GDALGetGCPSpatialRef()                         */
1962
/************************************************************************/
1963
1964
/**
1965
 * \brief Get output spatial reference system for GCPs.
1966
 *
1967
 * @since GDAL 3.0
1968
 *
1969
 * @see GDALDataset::GetGCPSpatialRef()
1970
 */
1971
1972
OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
1973
1974
0
{
1975
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1976
1977
0
    return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1978
0
        GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
1979
0
}
1980
1981
/************************************************************************/
1982
/*                        GDALGetGCPProjection()                        */
1983
/************************************************************************/
1984
1985
/**
1986
 * \brief Get output projection for GCPs.
1987
 *
1988
 * @see GDALDataset::GetGCPProjection()
1989
 */
1990
1991
const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
1992
1993
0
{
1994
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1995
1996
0
    return GDALDataset::FromHandle(hDS)->GetGCPProjection();
1997
0
}
1998
1999
/************************************************************************/
2000
/*                               GetGCPs()                              */
2001
/************************************************************************/
2002
2003
/**
2004
 * \brief Fetch GCPs.
2005
 *
2006
 * This method is the same as the C function GDALGetGCPs().
2007
 *
2008
 * @return pointer to internal GCP structure list.  It should not be modified,
2009
 * and may change on the next GDAL call.
2010
 */
2011
2012
const GDAL_GCP *GDALDataset::GetGCPs()
2013
0
{
2014
0
    return nullptr;
2015
0
}
2016
2017
/************************************************************************/
2018
/*                            GDALGetGCPs()                             */
2019
/************************************************************************/
2020
2021
/**
2022
 * \brief Fetch GCPs.
2023
 *
2024
 * @see GDALDataset::GetGCPs()
2025
 */
2026
2027
const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
2028
2029
0
{
2030
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
2031
2032
0
    return GDALDataset::FromHandle(hDS)->GetGCPs();
2033
0
}
2034
2035
/************************************************************************/
2036
/*                              SetGCPs()                               */
2037
/************************************************************************/
2038
2039
/**
2040
 * \brief Assign GCPs.
2041
 *
2042
 * This method is the same as the C function GDALSetGCPs().
2043
 *
2044
 * This method assigns the passed set of GCPs to this dataset, as well as
2045
 * setting their coordinate system.  Internally copies are made of the
2046
 * coordinate system and list of points, so the caller remains responsible for
2047
 * deallocating these arguments if appropriate.
2048
 *
2049
 * Most formats do not support setting of GCPs, even formats that can
2050
 * handle GCPs.  These formats will return CE_Failure.
2051
 *
2052
 * \note Startig with GDAL 3.0, this is a compatibility layer around
2053
 * SetGCPs(int, const GDAL_GCP*, const char*)
2054
 *
2055
 * @param nGCPCount number of GCPs being assigned.
2056
 *
2057
 * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2058
 *
2059
 * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
2060
 * GCP output coordinates.  This parameter should be "" if no output coordinate
2061
 * system is known.
2062
 *
2063
 * @return CE_None on success, CE_Failure on failure (including if action is
2064
 * not supported for this format).
2065
 */
2066
2067
CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
2068
                            const char *pszGCPProjection)
2069
2070
0
{
2071
0
    if (pszGCPProjection && pszGCPProjection[0] != '\0')
2072
0
    {
2073
0
        OGRSpatialReference oSRS;
2074
0
        oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2075
0
        if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
2076
0
        {
2077
0
            return CE_Failure;
2078
0
        }
2079
0
        return SetGCPs(nGCPCount, pasGCPList, &oSRS);
2080
0
    }
2081
0
    else
2082
0
    {
2083
0
        return SetGCPs(nGCPCount, pasGCPList,
2084
0
                       static_cast<const OGRSpatialReference *>(nullptr));
2085
0
    }
2086
0
}
2087
2088
/************************************************************************/
2089
/*                              SetGCPs()                               */
2090
/************************************************************************/
2091
2092
/**
2093
 * \brief Assign GCPs.
2094
 *
2095
 * This method is the same as the C function GDALSetGCPs().
2096
 *
2097
 * This method assigns the passed set of GCPs to this dataset, as well as
2098
 * setting their coordinate system.  Internally copies are made of the
2099
 * coordinate system and list of points, so the caller remains responsible for
2100
 * deallocating these arguments if appropriate.
2101
 *
2102
 * Most formats do not support setting of GCPs, even formats that can
2103
 * handle GCPs.  These formats will return CE_Failure.
2104
 *
2105
 * @since GDAL 3.0
2106
 *
2107
 * @param nGCPCount number of GCPs being assigned.
2108
 *
2109
 * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2110
 *
2111
 * @param poGCP_SRS the new coordinate reference system to assign for the
2112
 * GCP output coordinates.  This parameter should be null if no output
2113
 * coordinate system is known.
2114
 *
2115
 * @return CE_None on success, CE_Failure on failure (including if action is
2116
 * not supported for this format).
2117
 */
2118
2119
CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2120
                            CPL_UNUSED const GDAL_GCP *pasGCPList,
2121
                            CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2122
2123
0
{
2124
0
    if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2125
0
        ReportError(CE_Failure, CPLE_NotSupported,
2126
0
                    "Dataset does not support the SetGCPs() method.");
2127
2128
0
    return CE_Failure;
2129
0
}
2130
2131
/************************************************************************/
2132
/*                            GDALSetGCPs()                             */
2133
/************************************************************************/
2134
2135
/**
2136
 * \brief Assign GCPs.
2137
 *
2138
 * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
2139
 */
2140
2141
CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2142
                               const GDAL_GCP *pasGCPList,
2143
                               const char *pszGCPProjection)
2144
2145
0
{
2146
0
    VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2147
2148
0
    return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2149
0
                                                 pszGCPProjection);
2150
0
}
2151
2152
/************************************************************************/
2153
/*                           GDALSetGCPs2()                             */
2154
/************************************************************************/
2155
2156
/**
2157
 * \brief Assign GCPs.
2158
 *
2159
 * @since GDAL 3.0
2160
 * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
2161
 */
2162
2163
CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
2164
                    OGRSpatialReferenceH hSRS)
2165
2166
0
{
2167
0
    VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
2168
2169
0
    return GDALDataset::FromHandle(hDS)->SetGCPs(
2170
0
        nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
2171
0
}
2172
2173
/************************************************************************/
2174
/*                           BuildOverviews()                           */
2175
/************************************************************************/
2176
2177
/**
2178
 * \brief Build raster overview(s)
2179
 *
2180
 * If the operation is not supported for the indicated dataset, then
2181
 * CE_Failure is returned, and CPLGetLastErrorNo() will return
2182
 * CPLE_NotSupported.
2183
 *
2184
 * Depending on the actual file format, all overviews level can be also
2185
 * deleted by specifying nOverviews == 0. This works at least for external
2186
 * overviews (.ovr), TIFF internal overviews, etc.
2187
 *
2188
 * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
2189
 * to "ALL_CPUS" or a integer value to specify the number of threads to use for
2190
 * overview computation.
2191
 *
2192
 * This method is the same as the C function GDALBuildOverviewsEx().
2193
 *
2194
 * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
2195
 * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
2196
 * or "NONE" controlling the downsampling method applied.
2197
 * @param nOverviews number of overviews to build, or 0 to clean overviews.
2198
 * @param panOverviewList the list of overview decimation factors (positive
2199
 *                        integers, normally larger or equal to 2) to build, or
2200
 *                        NULL if nOverviews == 0.
2201
 * @param nListBands number of bands to build overviews for in panBandList.
2202
 * Build for all bands if this is 0.
2203
 * @param panBandList list of band numbers.
2204
 * @param pfnProgress a function to call to report progress, or NULL.
2205
 * @param pProgressData application data to pass to the progress function.
2206
 * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
2207
 *                     key=value pairs, or NULL
2208
 *
2209
 * @return CE_None on success or CE_Failure if the operation doesn't work.
2210
 *
2211
 * For example, to build overview level 2, 4 and 8 on all bands the following
2212
 * call could be made:
2213
 * \code{.cpp}
2214
 *   int       anOverviewList[3] = { 2, 4, 8 };
2215
 *
2216
 *   poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
2217
 *                              GDALDummyProgress, nullptr );
2218
 * \endcode
2219
 *
2220
 * @see GDALRegenerateOverviewsEx()
2221
 */
2222
2223
CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
2224
                                   const int *panOverviewList, int nListBands,
2225
                                   const int *panBandList,
2226
                                   GDALProgressFunc pfnProgress,
2227
                                   void *pProgressData,
2228
                                   CSLConstList papszOptions)
2229
0
{
2230
0
    int *panAllBandList = nullptr;
2231
2232
0
    if (nListBands == 0)
2233
0
    {
2234
0
        nListBands = GetRasterCount();
2235
0
        panAllBandList =
2236
0
            static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2237
0
        for (int i = 0; i < nListBands; ++i)
2238
0
            panAllBandList[i] = i + 1;
2239
2240
0
        panBandList = panAllBandList;
2241
0
    }
2242
2243
0
    if (pfnProgress == nullptr)
2244
0
        pfnProgress = GDALDummyProgress;
2245
2246
0
    for (int i = 0; i < nOverviews; ++i)
2247
0
    {
2248
0
        if (panOverviewList[i] <= 0)
2249
0
        {
2250
0
            CPLError(CE_Failure, CPLE_IllegalArg,
2251
0
                     "panOverviewList[%d] = %d is invalid. It must be a "
2252
0
                     "positive value",
2253
0
                     i, panOverviewList[i]);
2254
0
            CPLFree(panAllBandList);
2255
0
            return CE_Failure;
2256
0
        }
2257
0
    }
2258
2259
    // At time of writing, all overview generation options are actually
2260
    // expected to be passed as configuration options.
2261
0
    std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;
2262
0
    for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(papszOptions))
2263
0
    {
2264
0
        apoConfigOptionSetter.emplace_back(
2265
0
            std::make_unique<CPLConfigOptionSetter>(pszKey, pszValue, false));
2266
0
    }
2267
2268
0
    const CPLErr eErr =
2269
0
        IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
2270
0
                        panBandList, pfnProgress, pProgressData, papszOptions);
2271
2272
0
    if (panAllBandList != nullptr)
2273
0
        CPLFree(panAllBandList);
2274
2275
0
    return eErr;
2276
0
}
2277
2278
/************************************************************************/
2279
/*                         GDALBuildOverviews()                         */
2280
/************************************************************************/
2281
2282
/**
2283
 * \brief Build raster overview(s)
2284
 *
2285
 * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
2286
 */
2287
2288
CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
2289
                                      const char *pszResampling, int nOverviews,
2290
                                      const int *panOverviewList,
2291
                                      int nListBands, const int *panBandList,
2292
                                      GDALProgressFunc pfnProgress,
2293
                                      void *pProgressData)
2294
2295
0
{
2296
0
    VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2297
2298
0
    return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2299
0
        pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2300
0
        pfnProgress, pProgressData, nullptr);
2301
0
}
2302
2303
/************************************************************************/
2304
/*                         GDALBuildOverviews()                         */
2305
/************************************************************************/
2306
2307
/**
2308
 * \brief Build raster overview(s)
2309
 *
2310
 * @see GDALDataset::BuildOverviews()
2311
 * @since GDAL 3.6
2312
 */
2313
2314
CPLErr CPL_STDCALL
2315
GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
2316
                     int nOverviews, const int *panOverviewList, int nListBands,
2317
                     const int *panBandList, GDALProgressFunc pfnProgress,
2318
                     void *pProgressData, CSLConstList papszOptions)
2319
2320
0
{
2321
0
    VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2322
2323
0
    return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2324
0
        pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2325
0
        pfnProgress, pProgressData, papszOptions);
2326
0
}
2327
2328
/************************************************************************/
2329
/*                          IBuildOverviews()                           */
2330
/*                                                                      */
2331
/*      Default implementation.                                         */
2332
/************************************************************************/
2333
2334
//! @cond Doxygen_Suppress
2335
CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
2336
                                    const int *panOverviewList, int nListBands,
2337
                                    const int *panBandList,
2338
                                    GDALProgressFunc pfnProgress,
2339
                                    void *pProgressData,
2340
                                    CSLConstList papszOptions)
2341
2342
0
{
2343
0
    if (oOvManager.IsInitialized())
2344
0
        return oOvManager.BuildOverviews(
2345
0
            nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2346
0
            panBandList, pfnProgress, pProgressData, papszOptions);
2347
0
    else
2348
0
    {
2349
0
        ReportError(CE_Failure, CPLE_NotSupported,
2350
0
                    "BuildOverviews() not supported for this dataset.");
2351
2352
0
        return CE_Failure;
2353
0
    }
2354
0
}
2355
2356
//! @endcond
2357
2358
/************************************************************************/
2359
/*                            AddOverviews()                            */
2360
/*                                                                      */
2361
/*      Default implementation.                                         */
2362
/************************************************************************/
2363
2364
/**
2365
 * \brief Add overview from existing dataset(s)
2366
 *
2367
 * This function creates new overview levels or refresh existing one from
2368
 * the list of provided overview datasets.
2369
 * Source overviews may come from any GDAL supported format, provided they
2370
 * have the same number of bands and geospatial extent than the target
2371
 * dataset.
2372
 *
2373
 * If the operation is not supported for the indicated dataset, then
2374
 * CE_Failure is returned, and CPLGetLastErrorNo() will return
2375
 * CPLE_NotSupported.
2376
 *
2377
 * At time of writing, this method is only implemented for internal overviews
2378
 * of GeoTIFF datasets and external overviews in GeoTIFF format.
2379
 *
2380
 * @param apoSrcOvrDS Vector of source overviews.
2381
 * @param pfnProgress a function to call to report progress, or NULL.
2382
 * @param pProgressData application data to pass to the progress function.
2383
 * @param papszOptions NULL terminated list of options as
2384
 *                     key=value pairs, or NULL. None currently
2385
 *
2386
 * @return CE_None on success or CE_Failure if the operation doesn't work.
2387
 * @since 3.12
2388
 */
2389
CPLErr GDALDataset::AddOverviews(const std::vector<GDALDataset *> &apoSrcOvrDS,
2390
                                 GDALProgressFunc pfnProgress,
2391
                                 void *pProgressData, CSLConstList papszOptions)
2392
0
{
2393
0
    if (oOvManager.IsInitialized())
2394
0
    {
2395
0
        return oOvManager.AddOverviews(nullptr, apoSrcOvrDS, pfnProgress,
2396
0
                                       pProgressData, papszOptions);
2397
0
    }
2398
0
    else
2399
0
    {
2400
0
        ReportError(CE_Failure, CPLE_NotSupported,
2401
0
                    "AddOverviews() not supported for this dataset.");
2402
0
        return CE_Failure;
2403
0
    }
2404
0
}
2405
2406
/************************************************************************/
2407
/*                             IRasterIO()                              */
2408
/*                                                                      */
2409
/*      The default implementation of IRasterIO() is, in the general    */
2410
/*      case to pass the request off to each band objects rasterio      */
2411
/*      methods with appropriate arguments. In some cases, it might     */
2412
/*      choose instead the BlockBasedRasterIO() implementation.         */
2413
/************************************************************************/
2414
2415
//! @cond Doxygen_Suppress
2416
CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2417
                              int nXSize, int nYSize, void *pData,
2418
                              int nBufXSize, int nBufYSize,
2419
                              GDALDataType eBufType, int nBandCount,
2420
                              BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
2421
                              GSpacing nLineSpace, GSpacing nBandSpace,
2422
                              GDALRasterIOExtraArg *psExtraArg)
2423
2424
0
{
2425
0
    const char *pszInterleave = nullptr;
2426
2427
0
    CPLAssert(nullptr != pData);
2428
2429
0
    const bool bHasSubpixelShift =
2430
0
        psExtraArg->bFloatingPointWindowValidity &&
2431
0
        psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2432
0
        (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2433
2434
0
    if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2435
0
        nBandCount > 1 &&
2436
0
        (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2437
0
            nullptr &&
2438
0
        EQUAL(pszInterleave, "PIXEL"))
2439
0
    {
2440
0
        return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2441
0
                                  nBufXSize, nBufYSize, eBufType, nBandCount,
2442
0
                                  panBandMap, nPixelSpace, nLineSpace,
2443
0
                                  nBandSpace, psExtraArg);
2444
0
    }
2445
2446
0
    if (eRWFlag == GF_Read &&
2447
0
        (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2448
0
         psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2449
0
         psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2450
0
         psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2451
0
        !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2452
0
    {
2453
0
        if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2454
0
        {
2455
0
            int bTried = FALSE;
2456
0
            const CPLErr eErr = TryOverviewRasterIO(
2457
0
                eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2458
0
                nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2459
0
                nLineSpace, nBandSpace, psExtraArg, &bTried);
2460
0
            if (bTried)
2461
0
                return eErr;
2462
0
        }
2463
2464
0
        GDALDataType eFirstBandDT = GDT_Unknown;
2465
0
        int nFirstMaskFlags = 0;
2466
0
        GDALRasterBand *poFirstMaskBand = nullptr;
2467
0
        int nOKBands = 0;
2468
2469
        // Check if bands share the same mask band
2470
0
        for (int i = 0; i < nBandCount; ++i)
2471
0
        {
2472
0
            GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2473
0
            if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2474
0
                poBand->GetOverviewCount())
2475
0
            {
2476
                // Could be improved to select the appropriate overview.
2477
0
                break;
2478
0
            }
2479
0
            if (poBand->GetColorTable() != nullptr)
2480
0
            {
2481
0
                break;
2482
0
            }
2483
0
            const GDALDataType eDT = poBand->GetRasterDataType();
2484
0
            if (GDALDataTypeIsComplex(eDT))
2485
0
            {
2486
0
                break;
2487
0
            }
2488
0
            if (i == 0)
2489
0
            {
2490
0
                eFirstBandDT = eDT;
2491
0
                nFirstMaskFlags = poBand->GetMaskFlags();
2492
0
                if (nFirstMaskFlags == GMF_NODATA)
2493
0
                {
2494
                    // The dataset-level resampling code is not ready for nodata
2495
                    // Fallback to band-level resampling
2496
0
                    break;
2497
0
                }
2498
0
                poFirstMaskBand = poBand->GetMaskBand();
2499
0
            }
2500
0
            else
2501
0
            {
2502
0
                if (eDT != eFirstBandDT)
2503
0
                {
2504
0
                    break;
2505
0
                }
2506
0
                int nMaskFlags = poBand->GetMaskFlags();
2507
0
                if (nMaskFlags == GMF_NODATA)
2508
0
                {
2509
                    // The dataset-level resampling code is not ready for nodata
2510
                    // Fallback to band-level resampling
2511
0
                    break;
2512
0
                }
2513
0
                GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2514
0
                if (nFirstMaskFlags == GMF_ALL_VALID &&
2515
0
                    nMaskFlags == GMF_ALL_VALID)
2516
0
                {
2517
                    // Ok.
2518
0
                }
2519
0
                else if (poFirstMaskBand == poMaskBand)
2520
0
                {
2521
                    // Ok.
2522
0
                }
2523
0
                else
2524
0
                {
2525
0
                    break;
2526
0
                }
2527
0
            }
2528
2529
0
            ++nOKBands;
2530
0
        }
2531
2532
0
        GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2533
0
        void *pProgressDataGlobal = psExtraArg->pProgressData;
2534
2535
0
        CPLErr eErr = CE_None;
2536
0
        if (nOKBands > 0)
2537
0
        {
2538
0
            if (nOKBands < nBandCount)
2539
0
            {
2540
0
                psExtraArg->pfnProgress = GDALScaledProgress;
2541
0
                psExtraArg->pProgressData = GDALCreateScaledProgress(
2542
0
                    0.0, static_cast<double>(nOKBands) / nBandCount,
2543
0
                    pfnProgressGlobal, pProgressDataGlobal);
2544
0
                if (psExtraArg->pProgressData == nullptr)
2545
0
                    psExtraArg->pfnProgress = nullptr;
2546
0
            }
2547
2548
0
            eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2549
0
                                     pData, nBufXSize, nBufYSize, eBufType,
2550
0
                                     nOKBands, panBandMap, nPixelSpace,
2551
0
                                     nLineSpace, nBandSpace, psExtraArg);
2552
2553
0
            if (nOKBands < nBandCount)
2554
0
            {
2555
0
                GDALDestroyScaledProgress(psExtraArg->pProgressData);
2556
0
            }
2557
0
        }
2558
0
        if (eErr == CE_None && nOKBands < nBandCount)
2559
0
        {
2560
0
            if (nOKBands > 0)
2561
0
            {
2562
0
                psExtraArg->pfnProgress = GDALScaledProgress;
2563
0
                psExtraArg->pProgressData = GDALCreateScaledProgress(
2564
0
                    static_cast<double>(nOKBands) / nBandCount, 1.0,
2565
0
                    pfnProgressGlobal, pProgressDataGlobal);
2566
0
                if (psExtraArg->pProgressData == nullptr)
2567
0
                    psExtraArg->pfnProgress = nullptr;
2568
0
            }
2569
0
            eErr = BandBasedRasterIO(
2570
0
                eRWFlag, nXOff, nYOff, nXSize, nYSize,
2571
0
                static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2572
0
                nBufYSize, eBufType, nBandCount - nOKBands,
2573
0
                panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2574
0
                psExtraArg);
2575
0
            if (nOKBands > 0)
2576
0
            {
2577
0
                GDALDestroyScaledProgress(psExtraArg->pProgressData);
2578
0
            }
2579
0
        }
2580
2581
0
        psExtraArg->pfnProgress = pfnProgressGlobal;
2582
0
        psExtraArg->pProgressData = pProgressDataGlobal;
2583
2584
0
        return eErr;
2585
0
    }
2586
2587
0
    return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2588
0
                             nBufXSize, nBufYSize, eBufType, nBandCount,
2589
0
                             panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2590
0
                             psExtraArg);
2591
0
}
2592
2593
//! @endcond
2594
2595
/************************************************************************/
2596
/*                         BandBasedRasterIO()                          */
2597
/*                                                                      */
2598
/*      Pass the request off to each band objects rasterio methods with */
2599
/*      appropriate arguments.                                          */
2600
/************************************************************************/
2601
2602
//! @cond Doxygen_Suppress
2603
CPLErr GDALDataset::BandBasedRasterIO(
2604
    GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
2605
    void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
2606
    int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
2607
    GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
2608
2609
0
{
2610
0
    int iBandIndex;
2611
0
    CPLErr eErr = CE_None;
2612
2613
0
    GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2614
0
    void *pProgressDataGlobal = psExtraArg->pProgressData;
2615
2616
0
    for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2617
0
         ++iBandIndex)
2618
0
    {
2619
0
        GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2620
2621
0
        if (poBand == nullptr)
2622
0
        {
2623
0
            eErr = CE_Failure;
2624
0
            break;
2625
0
        }
2626
2627
0
        GByte *pabyBandData =
2628
0
            static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2629
2630
0
        if (nBandCount > 1)
2631
0
        {
2632
0
            psExtraArg->pfnProgress = GDALScaledProgress;
2633
0
            psExtraArg->pProgressData = GDALCreateScaledProgress(
2634
0
                1.0 * iBandIndex / nBandCount,
2635
0
                1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2636
0
                pProgressDataGlobal);
2637
0
            if (psExtraArg->pProgressData == nullptr)
2638
0
                psExtraArg->pfnProgress = nullptr;
2639
0
        }
2640
2641
0
        eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2642
0
                                 pabyBandData, nBufXSize, nBufYSize, eBufType,
2643
0
                                 nPixelSpace, nLineSpace, psExtraArg);
2644
2645
0
        if (nBandCount > 1)
2646
0
            GDALDestroyScaledProgress(psExtraArg->pProgressData);
2647
0
    }
2648
2649
0
    psExtraArg->pfnProgress = pfnProgressGlobal;
2650
0
    psExtraArg->pProgressData = pProgressDataGlobal;
2651
2652
0
    return eErr;
2653
0
}
2654
2655
//! @endcond
2656
2657
/************************************************************************/
2658
/*               ValidateRasterIOOrAdviseReadParameters()               */
2659
/************************************************************************/
2660
2661
//! @cond Doxygen_Suppress
2662
CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2663
    const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
2664
    int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
2665
    int nBandCount, const int *panBandMap)
2666
0
{
2667
2668
    /* -------------------------------------------------------------------- */
2669
    /*      Some size values are "noop".  Lets just return to avoid         */
2670
    /*      stressing lower level functions.                                */
2671
    /* -------------------------------------------------------------------- */
2672
0
    if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2673
0
    {
2674
0
        CPLDebug("GDAL",
2675
0
                 "%s skipped for odd window or buffer size.\n"
2676
0
                 "  Window = (%d,%d)x%dx%d\n"
2677
0
                 "  Buffer = %dx%d",
2678
0
                 pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2679
0
                 nBufYSize);
2680
2681
0
        *pbStopProcessingOnCENone = TRUE;
2682
0
        return CE_None;
2683
0
    }
2684
2685
0
    CPLErr eErr = CE_None;
2686
0
    *pbStopProcessingOnCENone = FALSE;
2687
2688
0
    if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2689
0
        nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2690
0
        nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2691
0
    {
2692
0
        ReportError(CE_Failure, CPLE_IllegalArg,
2693
0
                    "Access window out of range in %s.  Requested "
2694
0
                    "(%d,%d) of size %dx%d on raster of %dx%d.",
2695
0
                    pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2696
0
                    nRasterYSize);
2697
0
        eErr = CE_Failure;
2698
0
    }
2699
2700
0
    if (panBandMap == nullptr && nBandCount > GetRasterCount())
2701
0
    {
2702
0
        ReportError(CE_Failure, CPLE_IllegalArg,
2703
0
                    "%s: nBandCount cannot be greater than %d", pszCallingFunc,
2704
0
                    GetRasterCount());
2705
0
        eErr = CE_Failure;
2706
0
    }
2707
2708
0
    for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2709
0
    {
2710
0
        int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2711
0
        if (iBand < 1 || iBand > GetRasterCount())
2712
0
        {
2713
0
            ReportError(
2714
0
                CE_Failure, CPLE_IllegalArg,
2715
0
                "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2716
0
                pszCallingFunc, i, iBand);
2717
0
            eErr = CE_Failure;
2718
0
        }
2719
2720
0
        if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
2721
0
        {
2722
0
            ReportError(
2723
0
                CE_Failure, CPLE_IllegalArg,
2724
0
                "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2725
0
                pszCallingFunc, i, iBand);
2726
0
            eErr = CE_Failure;
2727
0
        }
2728
0
    }
2729
2730
0
    return eErr;
2731
0
}
2732
2733
//! @endcond
2734
2735
/************************************************************************/
2736
/*                              RasterIO()                              */
2737
/************************************************************************/
2738
2739
/**
2740
 * \brief Read/write a region of image data from multiple bands.
2741
 *
2742
 * This method allows reading a region of one or more GDALRasterBands from
2743
 * this dataset into a buffer,  or writing data from a buffer into a region
2744
 * of the GDALRasterBands.  It automatically takes care of data type
2745
 * translation if the data type (eBufType) of the buffer is different than
2746
 * that of the GDALRasterBand.
2747
 * The method also takes care of image decimation / replication if the
2748
 * buffer size (nBufXSize x nBufYSize) is different than the size of the
2749
 * region being accessed (nXSize x nYSize).
2750
 *
2751
 * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be
2752
 * fully within the raster space, that is nXOff >= 0, nYOff >= 0,
2753
 * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().
2754
 * If reads larger than the raster space are wished, GDALTranslate() might be used.
2755
 * Or use nLineSpace and a possibly shifted pData value.
2756
 *
2757
 * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2758
 * writing from various organization of buffers.
2759
 *
2760
 * Some formats may efficiently implement decimation into a buffer by
2761
 * reading from lower resolution overview images. The logic of the default
2762
 * implementation in the base class GDALRasterBand is the following one. It
2763
 * computes a target_downscaling_factor from the window of interest and buffer
2764
 * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
2765
 * It then walks through overviews and will select the first one whose
2766
 * downscaling factor is greater than target_downscaling_factor / 1.2.
2767
 *
2768
 * Let's assume we have overviews at downscaling factors 2, 4 and 8.
2769
 * The relationship between target_downscaling_factor and the select overview
2770
 * level is the following one:
2771
 *
2772
 * target_downscaling_factor  | selected_overview
2773
 * -------------------------  | -----------------
2774
 * ]0,       2 / 1.2]         | full resolution band
2775
 * ]2 / 1.2, 4 / 1.2]         | 2x downsampled band
2776
 * ]4 / 1.2, 8 / 1.2]         | 4x downsampled band
2777
 * ]8 / 1.2, infinity[        | 8x downsampled band
2778
 *
2779
 * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
2780
 * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
2781
 * option. Also note that starting with GDAL 3.9, when the resampling algorithm
2782
 * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
2783
 * this oversampling threshold defaults to 1. Consequently if there are overviews
2784
 * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
2785
 * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
2786
 *
2787
 * For highest performance full resolution data access, read and write
2788
 * on "block boundaries" as returned by GetBlockSize(), or use the
2789
 * ReadBlock() and WriteBlock() methods.
2790
 *
2791
 * This method is the same as the C GDALDatasetRasterIO() or
2792
 * GDALDatasetRasterIOEx() functions.
2793
 *
2794
 * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2795
 * write a region of data.
2796
 *
2797
 * @param nXOff The pixel offset to the top left corner of the region
2798
 * of the band to be accessed.  This would be zero to start from the left side.
2799
 *
2800
 * @param nYOff The line offset to the top left corner of the region
2801
 * of the band to be accessed.  This would be zero to start from the top.
2802
 *
2803
 * @param nXSize The width of the region of the band to be accessed in pixels.
2804
 *
2805
 * @param nYSize The height of the region of the band to be accessed in lines.
2806
 *
2807
 * @param pData The buffer into which the data should be read, or from which
2808
 * it should be written.  This buffer must contain at least
2809
 * nBufXSize * nBufYSize * nBandCount words of type eBufType.  It is organized
2810
 * in left to right,top to bottom pixel order.  Spacing is controlled by the
2811
 * nPixelSpace, and nLineSpace parameters.
2812
 * Note that even with eRWFlag==GF_Write, the content of the buffer might be
2813
 * temporarily modified during the execution of this method (and eventually
2814
 * restored back to its original content), so it is not safe to use a buffer
2815
 * stored in a read-only section of the calling program.
2816
 *
2817
 * @param nBufXSize the width of the buffer image into which the desired region
2818
 * is to be read, or from which it is to be written.
2819
 *
2820
 * @param nBufYSize the height of the buffer image into which the desired
2821
 * region is to be read, or from which it is to be written.
2822
 *
2823
 * @param eBufType the type of the pixel values in the pData data buffer. The
2824
 * pixel values will automatically be translated to/from the GDALRasterBand
2825
 * data type as needed. Most driver implementations will use GDALCopyWords64()
2826
 * to perform data type translation.
2827
 *
2828
 * @param nBandCount the number of bands being read or written.
2829
 *
2830
 * @param panBandMap the list of nBandCount band numbers being read/written.
2831
 * Note band numbers are 1 based. This may be NULL to select the first
2832
 * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and
2833
 * not "const int*")
2834
 *
2835
 * @param nPixelSpace The byte offset from the start of one pixel value in
2836
 * pData to the start of the next pixel value within a scanline. If defaulted
2837
 * (0) the size of the datatype eBufType is used.
2838
 *
2839
 * @param nLineSpace The byte offset from the start of one scanline in
2840
 * pData to the start of the next. If defaulted (0) the size of the datatype
2841
 * eBufType * nBufXSize is used.
2842
 *
2843
 * @param nBandSpace the byte offset from the start of one bands data to the
2844
 * start of the next. If defaulted (0) the value will be
2845
 * nLineSpace * nBufYSize implying band sequential organization
2846
 * of the data buffer.
2847
 *
2848
 * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
2849
 * structure with additional arguments to specify resampling and progress
2850
 * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
2851
 * configuration option can also be defined to override the default resampling
2852
 * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
2853
 *
2854
 * @return CE_Failure if the access fails, otherwise CE_None.
2855
 */
2856
2857
CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2858
                             int nXSize, int nYSize, void *pData, int nBufXSize,
2859
                             int nBufYSize, GDALDataType eBufType,
2860
                             int nBandCount, const int *panBandMap,
2861
                             GSpacing nPixelSpace, GSpacing nLineSpace,
2862
                             GSpacing nBandSpace,
2863
                             GDALRasterIOExtraArg *psExtraArg)
2864
2865
0
{
2866
0
    GDALRasterIOExtraArg sExtraArg;
2867
0
    if (psExtraArg == nullptr)
2868
0
    {
2869
0
        INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2870
2871
        // 4 below inits are not strictly needed but make Coverity Scan
2872
        // happy
2873
0
        sExtraArg.dfXOff = nXOff;
2874
0
        sExtraArg.dfYOff = nYOff;
2875
0
        sExtraArg.dfXSize = nXSize;
2876
0
        sExtraArg.dfYSize = nYSize;
2877
2878
0
        psExtraArg = &sExtraArg;
2879
0
    }
2880
0
    else if (CPL_UNLIKELY(psExtraArg->nVersion >
2881
0
                          RASTERIO_EXTRA_ARG_CURRENT_VERSION))
2882
0
    {
2883
0
        ReportError(CE_Failure, CPLE_AppDefined,
2884
0
                    "Unhandled version of GDALRasterIOExtraArg");
2885
0
        return CE_Failure;
2886
0
    }
2887
2888
0
    GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2889
0
                                       nBufYSize);
2890
2891
0
    if (CPL_UNLIKELY(nullptr == pData))
2892
0
    {
2893
0
        ReportError(CE_Failure, CPLE_AppDefined,
2894
0
                    "The buffer into which the data should be read is null");
2895
0
        return CE_Failure;
2896
0
    }
2897
2898
    /* -------------------------------------------------------------------- */
2899
    /*      Do some validation of parameters.                               */
2900
    /* -------------------------------------------------------------------- */
2901
2902
0
    if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))
2903
0
    {
2904
0
        ReportError(
2905
0
            CE_Failure, CPLE_IllegalArg,
2906
0
            "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
2907
0
            eRWFlag);
2908
0
        return CE_Failure;
2909
0
    }
2910
2911
0
    if (eRWFlag == GF_Write)
2912
0
    {
2913
0
        if (CPL_UNLIKELY(eAccess != GA_Update))
2914
0
        {
2915
0
            ReportError(CE_Failure, CPLE_AppDefined,
2916
0
                        "Write operation not permitted on dataset opened "
2917
0
                        "in read-only mode");
2918
0
            return CE_Failure;
2919
0
        }
2920
0
    }
2921
2922
0
    int bStopProcessing = FALSE;
2923
0
    CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2924
0
        "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2925
0
        nBufYSize, nBandCount, panBandMap);
2926
0
    if (eErr != CE_None || bStopProcessing)
2927
0
        return eErr;
2928
0
    if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))
2929
0
    {
2930
0
        ReportError(CE_Failure, CPLE_AppDefined,
2931
0
                    "Illegal GDT_Unknown/GDT_TypeCount argument");
2932
0
        return CE_Failure;
2933
0
    }
2934
2935
    /* -------------------------------------------------------------------- */
2936
    /*      If pixel and line spacing are defaulted assign reasonable      */
2937
    /*      value assuming a packed buffer.                                 */
2938
    /* -------------------------------------------------------------------- */
2939
0
    if (nPixelSpace == 0)
2940
0
        nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2941
2942
0
    if (nLineSpace == 0)
2943
0
    {
2944
0
        nLineSpace = nPixelSpace * nBufXSize;
2945
0
    }
2946
2947
0
    if (nBandSpace == 0 && nBandCount > 1)
2948
0
    {
2949
0
        nBandSpace = nLineSpace * nBufYSize;
2950
0
    }
2951
2952
0
    if (panBandMap == nullptr)
2953
0
    {
2954
0
        if (!m_poPrivate)
2955
0
            return CE_Failure;
2956
0
        CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
2957
0
        panBandMap = m_poPrivate->m_anBandMap.data();
2958
0
    }
2959
2960
0
    int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2961
2962
    /* -------------------------------------------------------------------- */
2963
    /*      We are being forced to use cached IO instead of a driver        */
2964
    /*      specific implementation.                                        */
2965
    /* -------------------------------------------------------------------- */
2966
0
    if (bForceCachedIO)
2967
0
    {
2968
0
        eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2969
0
                                  nBufXSize, nBufYSize, eBufType, nBandCount,
2970
0
                                  panBandMap, nPixelSpace, nLineSpace,
2971
0
                                  nBandSpace, psExtraArg);
2972
0
    }
2973
2974
    /* -------------------------------------------------------------------- */
2975
    /*      Call the format specific function.                              */
2976
    /* -------------------------------------------------------------------- */
2977
0
    else
2978
0
    {
2979
0
        eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2980
0
                         nBufXSize, nBufYSize, eBufType, nBandCount,
2981
                         // TODO: remove this const_cast once IRasterIO()
2982
                         // takes a const int*
2983
0
                         const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,
2984
0
                         nBandSpace, psExtraArg);
2985
0
    }
2986
2987
0
    if (bCallLeaveReadWrite)
2988
0
        LeaveReadWrite();
2989
2990
0
    return eErr;
2991
0
}
2992
2993
/************************************************************************/
2994
/*                        GDALDatasetRasterIO()                         */
2995
/************************************************************************/
2996
2997
/**
2998
 * \brief Read/write a region of image data from multiple bands.
2999
 *
3000
 * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
3001
 * resolution, progress callback, etc. are needed)
3002
 *
3003
 * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
3004
 *
3005
 * @see GDALDataset::RasterIO()
3006
 */
3007
3008
CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
3009
                                       int nXOff, int nYOff, int nXSize,
3010
                                       int nYSize, void *pData, int nBufXSize,
3011
                                       int nBufYSize, GDALDataType eBufType,
3012
                                       int nBandCount, const int *panBandMap,
3013
                                       int nPixelSpace, int nLineSpace,
3014
                                       int nBandSpace)
3015
3016
0
{
3017
0
    VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
3018
3019
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3020
3021
0
    return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3022
0
                          nBufXSize, nBufYSize, eBufType, nBandCount,
3023
0
                          panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3024
0
                          nullptr);
3025
0
}
3026
3027
/************************************************************************/
3028
/*                       GDALDatasetRasterIOEx()                        */
3029
/************************************************************************/
3030
3031
/**
3032
 * \brief Read/write a region of image data from multiple bands.
3033
 *
3034
 * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
3035
 *
3036
 * @see GDALDataset::RasterIO()
3037
 * @since GDAL 2.0
3038
 */
3039
3040
CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
3041
    GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
3042
    int nYSize, void *pData, int nBufXSize, int nBufYSize,
3043
    GDALDataType eBufType, int nBandCount, const int *panBandMap,
3044
    GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
3045
    GDALRasterIOExtraArg *psExtraArg)
3046
3047
0
{
3048
0
    VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
3049
3050
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
3051
3052
0
    return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
3053
0
                          nBufXSize, nBufYSize, eBufType, nBandCount,
3054
0
                          panBandMap, nPixelSpace, nLineSpace, nBandSpace,
3055
0
                          psExtraArg);
3056
0
}
3057
3058
/************************************************************************/
3059
/*                          GetOpenDatasets()                           */
3060
/************************************************************************/
3061
3062
/**
3063
 * \brief Fetch all open GDAL dataset handles.
3064
 *
3065
 * This method is the same as the C function GDALGetOpenDatasets().
3066
 *
3067
 * NOTE: This method is not thread safe.  The returned list may change
3068
 * at any time and it should not be freed.
3069
 *
3070
 * @param pnCount integer into which to place the count of dataset pointers
3071
 * being returned.
3072
 *
3073
 * @return a pointer to an array of dataset handles.
3074
 */
3075
3076
GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
3077
3078
0
{
3079
0
    CPLMutexHolderD(&hDLMutex);
3080
3081
0
    if (poAllDatasetMap == nullptr)
3082
0
    {
3083
0
        *pnCount = 0;
3084
0
        return nullptr;
3085
0
    }
3086
3087
0
    *pnCount = static_cast<int>(poAllDatasetMap->size());
3088
0
    ppDatasets = static_cast<GDALDataset **>(
3089
0
        CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
3090
0
    std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
3091
0
    for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
3092
0
        ppDatasets[i] = oIter->first;
3093
0
    return ppDatasets;
3094
0
}
3095
3096
/************************************************************************/
3097
/*                        GDALGetOpenDatasets()                         */
3098
/************************************************************************/
3099
3100
/**
3101
 * \brief Fetch all open GDAL dataset handles.
3102
 *
3103
 * @see GDALDataset::GetOpenDatasets()
3104
 */
3105
3106
void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
3107
3108
0
{
3109
0
    VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
3110
0
    VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
3111
3112
0
    *ppahDSList =
3113
0
        reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
3114
0
}
3115
3116
/************************************************************************/
3117
/*                        GDALCleanOpenDatasetsList()                   */
3118
/************************************************************************/
3119
3120
// Useful when called from the child of a fork(), to avoid closing
3121
// the datasets of the parent at the child termination.
3122
void GDALNullifyOpenDatasetsList()
3123
0
{
3124
0
    poAllDatasetMap = nullptr;
3125
0
    phSharedDatasetSet = nullptr;
3126
0
    ppDatasets = nullptr;
3127
0
    hDLMutex = nullptr;
3128
0
}
3129
3130
/************************************************************************/
3131
/*                             GDALGetAccess()                          */
3132
/************************************************************************/
3133
3134
/**
3135
 * \brief Return access flag
3136
 *
3137
 * @see GDALDataset::GetAccess()
3138
 */
3139
3140
int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
3141
0
{
3142
0
    VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
3143
3144
0
    return GDALDataset::FromHandle(hDS)->GetAccess();
3145
0
}
3146
3147
/************************************************************************/
3148
/*                             AdviseRead()                             */
3149
/************************************************************************/
3150
3151
/**
3152
 * \brief Advise driver of upcoming read requests.
3153
 *
3154
 * Some GDAL drivers operate more efficiently if they know in advance what
3155
 * set of upcoming read requests will be made.  The AdviseRead() method allows
3156
 * an application to notify the driver of the region and bands of interest,
3157
 * and at what resolution the region will be read.
3158
 *
3159
 * Many drivers just ignore the AdviseRead() call, but it can dramatically
3160
 * accelerate access via some drivers.
3161
 *
3162
 * Depending on call paths, drivers might receive several calls to
3163
 * AdviseRead() with the same parameters.
3164
 *
3165
 * @param nXOff The pixel offset to the top left corner of the region
3166
 * of the band to be accessed.  This would be zero to start from the left side.
3167
 *
3168
 * @param nYOff The line offset to the top left corner of the region
3169
 * of the band to be accessed.  This would be zero to start from the top.
3170
 *
3171
 * @param nXSize The width of the region of the band to be accessed in pixels.
3172
 *
3173
 * @param nYSize The height of the region of the band to be accessed in lines.
3174
 *
3175
 * @param nBufXSize the width of the buffer image into which the desired region
3176
 * is to be read, or from which it is to be written.
3177
 *
3178
 * @param nBufYSize the height of the buffer image into which the desired
3179
 * region is to be read, or from which it is to be written.
3180
 *
3181
 * @param eBufType the type of the pixel values in the pData data buffer.  The
3182
 * pixel values will automatically be translated to/from the GDALRasterBand
3183
 * data type as needed.
3184
 *
3185
 * @param nBandCount the number of bands being read or written.
3186
 *
3187
 * @param panBandMap the list of nBandCount band numbers being read/written.
3188
 * Note band numbers are 1 based.   This may be NULL to select the first
3189
 * nBandCount bands.
3190
 *
3191
 * @param papszOptions a list of name=value strings with special control
3192
 * options.  Normally this is NULL.
3193
 *
3194
 * @return CE_Failure if the request is invalid and CE_None if it works or
3195
 * is ignored.
3196
 */
3197
3198
CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
3199
                               int nBufXSize, int nBufYSize,
3200
                               GDALDataType eBufType, int nBandCount,
3201
                               int *panBandMap, char **papszOptions)
3202
3203
0
{
3204
    /* -------------------------------------------------------------------- */
3205
    /*      Do some validation of parameters.                               */
3206
    /* -------------------------------------------------------------------- */
3207
0
    int bStopProcessing = FALSE;
3208
0
    CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3209
0
        "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3210
0
        nBufXSize, nBufYSize, nBandCount, panBandMap);
3211
0
    if (eErr != CE_None || bStopProcessing)
3212
0
        return eErr;
3213
3214
0
    for (int iBand = 0; iBand < nBandCount; ++iBand)
3215
0
    {
3216
0
        GDALRasterBand *poBand = nullptr;
3217
3218
0
        if (panBandMap == nullptr)
3219
0
            poBand = GetRasterBand(iBand + 1);
3220
0
        else
3221
0
            poBand = GetRasterBand(panBandMap[iBand]);
3222
3223
0
        if (poBand == nullptr)
3224
0
            return CE_Failure;
3225
3226
0
        eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3227
0
                                  nBufYSize, eBufType, papszOptions);
3228
3229
0
        if (eErr != CE_None)
3230
0
            return eErr;
3231
0
    }
3232
3233
0
    return CE_None;
3234
0
}
3235
3236
/************************************************************************/
3237
/*                       GDALDatasetAdviseRead()                        */
3238
/************************************************************************/
3239
3240
/**
3241
 * \brief Advise driver of upcoming read requests.
3242
 *
3243
 * @see GDALDataset::AdviseRead()
3244
 */
3245
CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
3246
                                         int nXSize, int nYSize, int nBufXSize,
3247
                                         int nBufYSize, GDALDataType eDT,
3248
                                         int nBandCount, int *panBandMap,
3249
                                         CSLConstList papszOptions)
3250
3251
0
{
3252
0
    VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
3253
3254
0
    return GDALDataset::FromHandle(hDS)->AdviseRead(
3255
0
        nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
3256
0
        panBandMap, const_cast<char **>(papszOptions));
3257
0
}
3258
3259
/************************************************************************/
3260
/*                         GDALAntiRecursionStruct                      */
3261
/************************************************************************/
3262
3263
// Prevent infinite recursion.
3264
struct GDALAntiRecursionStruct
3265
{
3266
    struct DatasetContext
3267
    {
3268
        std::string osFilename;
3269
        int nOpenFlags;
3270
        std::string osAllowedDrivers;
3271
3272
        DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3273
                       const std::string &osAllowedDriversIn)
3274
0
            : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3275
0
              osAllowedDrivers(osAllowedDriversIn)
3276
0
        {
3277
0
        }
3278
    };
3279
3280
    struct DatasetContextCompare
3281
    {
3282
        bool operator()(const DatasetContext &lhs,
3283
                        const DatasetContext &rhs) const
3284
0
        {
3285
0
            return lhs.osFilename < rhs.osFilename ||
3286
0
                   (lhs.osFilename == rhs.osFilename &&
3287
0
                    (lhs.nOpenFlags < rhs.nOpenFlags ||
3288
0
                     (lhs.nOpenFlags == rhs.nOpenFlags &&
3289
0
                      lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
3290
0
        }
3291
    };
3292
3293
    ~GDALAntiRecursionStruct()
3294
0
    {
3295
0
        CPLAssert(aosDatasetNamesWithFlags.empty());
3296
0
        CPLAssert(nRecLevel == 0);
3297
0
        CPLAssert(m_oMapDepth.empty());
3298
0
    }
3299
3300
    std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
3301
    int nRecLevel = 0;
3302
    std::map<std::string, int> m_oMapDepth{};
3303
};
3304
3305
#ifdef _WIN32
3306
// Currently thread_local and C++ objects don't work well with DLL on Windows
3307
static void FreeAntiRecursionOpen(void *pData)
3308
{
3309
    delete static_cast<GDALAntiRecursionStruct *>(pData);
3310
}
3311
3312
static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3313
{
3314
    static GDALAntiRecursionStruct dummy;
3315
    int bMemoryErrorOccurred = false;
3316
    void *pData =
3317
        CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
3318
    if (bMemoryErrorOccurred)
3319
    {
3320
        return dummy;
3321
    }
3322
    if (pData == nullptr)
3323
    {
3324
        auto pAntiRecursion = new GDALAntiRecursionStruct();
3325
        CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
3326
                                FreeAntiRecursionOpen, &bMemoryErrorOccurred);
3327
        if (bMemoryErrorOccurred)
3328
        {
3329
            delete pAntiRecursion;
3330
            return dummy;
3331
        }
3332
        return *pAntiRecursion;
3333
    }
3334
    return *static_cast<GDALAntiRecursionStruct *>(pData);
3335
}
3336
#else
3337
static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
3338
3339
static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3340
0
{
3341
0
    return g_tls_antiRecursion;
3342
0
}
3343
#endif
3344
3345
//! @cond Doxygen_Suppress
3346
GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3347
0
    : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3348
0
      m_osIdentifier(osIdentifier),
3349
0
      m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3350
0
{
3351
0
    CPLAssert(!osIdentifier.empty());
3352
0
}
3353
3354
GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3355
    const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3356
0
    : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3357
0
      m_osIdentifier(osIdentifier.empty()
3358
0
                         ? osIdentifier
3359
0
                         : other.m_osIdentifier + osIdentifier),
3360
0
      m_nDepth(m_osIdentifier.empty()
3361
0
                   ? 0
3362
0
                   : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3363
0
{
3364
0
}
3365
3366
GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3367
0
{
3368
0
    if (!m_osIdentifier.empty())
3369
0
    {
3370
0
        auto oIter = m_psAntiRecursionStruct->m_oMapDepth.find(m_osIdentifier);
3371
0
        CPLAssert(oIter != m_psAntiRecursionStruct->m_oMapDepth.end());
3372
0
        if (--(oIter->second) == 0)
3373
0
            m_psAntiRecursionStruct->m_oMapDepth.erase(oIter);
3374
0
    }
3375
0
}
3376
3377
//! @endcond
3378
3379
/************************************************************************/
3380
/*                            GetFileList()                             */
3381
/************************************************************************/
3382
3383
/**
3384
 * \brief Fetch files forming dataset.
3385
 *
3386
 * Returns a list of files believed to be part of this dataset.  If it returns
3387
 * an empty list of files it means there is believed to be no local file
3388
 * system files associated with the dataset (for instance a virtual dataset).
3389
 * The returned file list is owned by the caller and should be deallocated
3390
 * with CSLDestroy().
3391
 *
3392
 * The returned filenames will normally be relative or absolute paths
3393
 * depending on the path used to originally open the dataset.  The strings
3394
 * will be UTF-8 encoded.
3395
 *
3396
 * This method is the same as the C GDALGetFileList() function.
3397
 *
3398
 * @return NULL or a NULL terminated array of file names.
3399
 */
3400
3401
char **GDALDataset::GetFileList()
3402
3403
0
{
3404
0
    CPLString osMainFilename = GetDescription();
3405
0
    VSIStatBufL sStat;
3406
3407
0
    GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3408
0
    GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3409
0
                                                        std::string());
3410
0
    auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3411
0
    if (cpl::contains(aosDatasetList, datasetCtxt))
3412
0
        return nullptr;
3413
3414
    /* -------------------------------------------------------------------- */
3415
    /*      Is the main filename even a real filesystem object?             */
3416
    /* -------------------------------------------------------------------- */
3417
0
    int bMainFileReal =
3418
0
        VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3419
3420
    /* -------------------------------------------------------------------- */
3421
    /*      Form new list.                                                  */
3422
    /* -------------------------------------------------------------------- */
3423
0
    char **papszList = nullptr;
3424
3425
0
    if (bMainFileReal)
3426
0
        papszList = CSLAddString(papszList, osMainFilename);
3427
3428
0
    if (sAntiRecursion.nRecLevel == 100)
3429
0
    {
3430
0
        CPLError(CE_Failure, CPLE_AppDefined,
3431
0
                 "GetFileList() called with too many recursion levels");
3432
0
        return papszList;
3433
0
    }
3434
0
    ++sAntiRecursion.nRecLevel;
3435
3436
    /* -------------------------------------------------------------------- */
3437
    /*      Do we have a known overview file?                               */
3438
    /* -------------------------------------------------------------------- */
3439
0
    if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3440
0
    {
3441
0
        auto iter = aosDatasetList.insert(datasetCtxt).first;
3442
0
        char **papszOvrList = oOvManager.poODS->GetFileList();
3443
0
        papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3444
0
        CSLDestroy(papszOvrList);
3445
0
        aosDatasetList.erase(iter);
3446
0
    }
3447
3448
    /* -------------------------------------------------------------------- */
3449
    /*      Do we have a known mask file?                                   */
3450
    /* -------------------------------------------------------------------- */
3451
0
    if (oOvManager.HaveMaskFile())
3452
0
    {
3453
0
        auto iter = aosDatasetList.insert(std::move(datasetCtxt)).first;
3454
0
        for (const char *pszFile :
3455
0
             CPLStringList(oOvManager.poMaskDS->GetFileList()))
3456
0
        {
3457
0
            if (CSLFindString(papszList, pszFile) < 0)
3458
0
                papszList = CSLAddString(papszList, pszFile);
3459
0
        }
3460
0
        aosDatasetList.erase(iter);
3461
0
    }
3462
3463
0
    --sAntiRecursion.nRecLevel;
3464
3465
0
    return papszList;
3466
0
}
3467
3468
/************************************************************************/
3469
/*                          GDALGetFileList()                           */
3470
/************************************************************************/
3471
3472
/**
3473
 * \brief Fetch files forming dataset.
3474
 *
3475
 * @see GDALDataset::GetFileList()
3476
 */
3477
3478
char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3479
3480
0
{
3481
0
    VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3482
3483
0
    return GDALDataset::FromHandle(hDS)->GetFileList();
3484
0
}
3485
3486
/************************************************************************/
3487
/*                           CreateMaskBand()                           */
3488
/************************************************************************/
3489
3490
/**
3491
 * \brief Adds a mask band to the dataset
3492
 *
3493
 * The default implementation of the CreateMaskBand() method is implemented
3494
 * based on similar rules to the .ovr handling implemented using the
3495
 * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3496
 * be created with the same basename as the original file, and it will have
3497
 * one band.
3498
 * The mask images will be deflate compressed tiled images with the same
3499
 * block size as the original image if possible.
3500
 * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3501
 * level, where xx matches the band number of a band of the main dataset. The
3502
 * value of those items will be the one of the nFlagsIn parameter.
3503
 *
3504
 * Note that if you got a mask band with a previous call to GetMaskBand(), it
3505
 * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3506
 * again.
3507
 *
3508
 * @since GDAL 1.5.0
3509
 *
3510
 * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3511
 *                 GMF_PER_DATASET will be always set, even if not explicitly
3512
 *                 specified.
3513
 * @return CE_None on success or CE_Failure on an error.
3514
 *
3515
 * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3516
 * @see GDALRasterBand::CreateMaskBand()
3517
 *
3518
 */
3519
CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
3520
3521
0
{
3522
0
    if (oOvManager.IsInitialized())
3523
0
    {
3524
0
        CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3525
0
        if (eErr != CE_None)
3526
0
            return eErr;
3527
3528
        // Invalidate existing raster band masks.
3529
0
        for (int i = 0; i < nBands; ++i)
3530
0
        {
3531
0
            GDALRasterBand *poBand = papoBands[i];
3532
0
            poBand->poMask.reset();
3533
0
        }
3534
3535
0
        return CE_None;
3536
0
    }
3537
3538
0
    ReportError(CE_Failure, CPLE_NotSupported,
3539
0
                "CreateMaskBand() not supported for this dataset.");
3540
3541
0
    return CE_Failure;
3542
0
}
3543
3544
/************************************************************************/
3545
/*                     GDALCreateDatasetMaskBand()                      */
3546
/************************************************************************/
3547
3548
/**
3549
 * \brief Adds a mask band to the dataset
3550
 * @see GDALDataset::CreateMaskBand()
3551
 */
3552
CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3553
3554
0
{
3555
0
    VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3556
3557
0
    return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3558
0
}
3559
3560
/************************************************************************/
3561
/*                              GDALOpen()                              */
3562
/************************************************************************/
3563
3564
/**
3565
 * \brief Open a raster file as a GDALDataset.
3566
 *
3567
 * This function will try to open the passed file, or virtual dataset
3568
 * name by invoking the Open method of each registered GDALDriver in turn.
3569
 * The first successful open will result in a returned dataset.  If all
3570
 * drivers fail then NULL is returned and an error is issued.
3571
 *
3572
 * Several recommendations :
3573
 * <ul>
3574
 * <li>If you open a dataset object with GA_Update access, it is not recommended
3575
 * to open a new dataset on the same underlying file.</li>
3576
 * <li>The returned dataset should only be accessed by one thread at a time. If
3577
 * you want to use it from different threads, you must add all necessary code
3578
 * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
3579
 * as GeoTIFF, maintain internal state variables that are updated each time a
3580
 * new block is read, thus preventing concurrent use.) </li>
3581
 * </ul>
3582
 *
3583
 * For drivers supporting the VSI virtual file API, it is possible to open a
3584
 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3585
 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3586
 * server (see VSIInstallCurlFileHandler())
3587
 *
3588
 * \sa GDALOpenShared()
3589
 * \sa GDALOpenEx()
3590
 *
3591
 * @param pszFilename the name of the file to access.  In the case of
3592
 * exotic drivers this may not refer to a physical file, but instead contain
3593
 * information for the driver on how to access a dataset.  It should be in UTF-8
3594
 * encoding.
3595
 *
3596
 * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
3597
 * drivers support only read only access.
3598
 *
3599
 * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
3600
 * this handle can be cast to a GDALDataset *.
3601
 */
3602
3603
GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3604
3605
0
{
3606
0
    const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3607
0
    const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3608
0
    GDALDatasetH hDataset =
3609
0
        GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3610
0
    return hDataset;
3611
0
}
3612
3613
/************************************************************************/
3614
/*                             GetSharedDS()                            */
3615
/************************************************************************/
3616
3617
static GDALDataset *GetSharedDS(const char *pszFilename,
3618
                                unsigned int nOpenFlags,
3619
                                const char *const *papszOpenOptions)
3620
0
{
3621
0
    CPLMutexHolderD(&hDLMutex);
3622
3623
0
    if (phSharedDatasetSet != nullptr)
3624
0
    {
3625
0
        const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3626
0
        SharedDatasetCtxt sStruct;
3627
3628
0
        sStruct.nPID = nThisPID;
3629
0
        sStruct.pszDescription = const_cast<char *>(pszFilename);
3630
0
        sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3631
0
        std::string osConcatenatedOpenOptions =
3632
0
            GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3633
0
        sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3634
0
        sStruct.poDS = nullptr;
3635
0
        SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3636
0
            CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3637
0
        if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3638
0
        {
3639
0
            sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3640
0
            psStruct = static_cast<SharedDatasetCtxt *>(
3641
0
                CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3642
0
        }
3643
0
        if (psStruct)
3644
0
        {
3645
0
            return psStruct->poDS;
3646
0
        }
3647
0
    }
3648
0
    return nullptr;
3649
0
}
3650
3651
/************************************************************************/
3652
/*                             GDALOpenEx()                             */
3653
/************************************************************************/
3654
3655
/**
3656
 * \brief Open a raster or vector file as a GDALDataset.
3657
 *
3658
 * This function will try to open the passed file, or virtual dataset
3659
 * name by invoking the Open method of each registered GDALDriver in turn.
3660
 * The first successful open will result in a returned dataset.  If all
3661
 * drivers fail then NULL is returned and an error is issued.
3662
 *
3663
 * Several recommendations :
3664
 * <ul>
3665
 * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3666
 * recommended to open a new dataset on the same underlying file.</li>
3667
 * <li>The returned dataset should only be accessed by one thread at a time. If
3668
 * you want to use it from different threads, you must add all necessary code
3669
 * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
3670
 * as GeoTIFF, maintain internal state variables that are updated each time a
3671
 * new block is read, thus preventing concurrent use.) </li>
3672
 * </ul>
3673
 *
3674
 * For drivers supporting the VSI virtual file API, it is possible to open a
3675
 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3676
 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3677
 * server (see VSIInstallCurlFileHandler())
3678
 *
3679
 * In order to reduce the need for searches through the operating system
3680
 * file system machinery, it is possible to give an optional list of files with
3681
 * the papszSiblingFiles parameter.
3682
 * This is the list of all files at the same level in the file system as the
3683
 * target file, including the target file. The filenames must not include any
3684
 * path components, are essentially just the output of VSIReadDir() on the
3685
 * parent directory. If the target object does not have filesystem semantics
3686
 * then the file list should be NULL.
3687
 *
3688
 * @param pszFilename the name of the file to access.  In the case of
3689
 * exotic drivers this may not refer to a physical file, but instead contain
3690
 * information for the driver on how to access a dataset.  It should be in UTF-8
3691
 * encoding.
3692
 *
3693
 * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3694
 * through logical or operator.
3695
 * <ul>
3696
 * <li>Driver kind:
3697
 *   <ul>
3698
 *     <li>GDAL_OF_RASTER for raster drivers,</li>
3699
 *     <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
3700
 *     <li>GDAL_OF_VECTOR for vector drivers,</li>
3701
 *     <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
3702
 *    </ul>
3703
 * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
3704
 * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
3705
 * | GDAL_OF_GNM is implied.
3706
 * </li>
3707
 * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.
3708
 * </li>
3709
 * <li>Shared mode: GDAL_OF_SHARED. If set,
3710
 * it allows the sharing of GDALDataset handles for a dataset with other callers
3711
 * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
3712
 * its list of currently open and shared GDALDataset's, and if the
3713
 * GetDescription() name for one exactly matches the pszFilename passed to
3714
 * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
3715
 * from the same thread.
3716
 * </li>
3717
 * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).
3718
 * This must be use in combination with GDAL_OF_RASTER, and is mutually
3719
 * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or
3720
 * GDAL_OF_GNM.
3721
 * </li>
3722
 * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
3723
 * a failed attempt to open the file will lead to an error message to be
3724
 * reported.
3725
 * </li>
3726
 * </ul>
3727
 *
3728
 * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3729
 * terminated list of strings with the driver short names that must be
3730
 * considered.
3731
 *
3732
 * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3733
 * options passed to candidate drivers. An option exists for all drivers,
3734
 * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3735
 * The level index starts at 0. The level number can be suffixed by "only" to
3736
 * specify that only this overview level must be visible, and not sub-levels.
3737
 * Open options are validated by default, and a warning is emitted in case the
3738
 * option is not recognized. In some scenarios, it might be not desirable (e.g.
3739
 * when not knowing which driver will open the file), so the special open option
3740
 * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3741
 * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3742
 * that it may not cause a warning if the driver doesn't declare this option.
3743
 * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3744
 * no overviews should be exposed.
3745
 *
3746
 * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3747
 * filenames that are auxiliary to the main filename. If NULL is passed, a
3748
 * probing of the file system will be done.
3749
 *
3750
 * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
3751
 * this handle can be cast to a GDALDataset *.
3752
 *
3753
 * @since GDAL 2.0
3754
 */
3755
3756
GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
3757
                                    unsigned int nOpenFlags,
3758
                                    const char *const *papszAllowedDrivers,
3759
                                    const char *const *papszOpenOptions,
3760
                                    const char *const *papszSiblingFiles)
3761
0
{
3762
0
    VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3763
3764
    // Hack for the ZARR driver. We translate the CACHE_KERCHUNK_JSON
3765
    // into VSIKERCHUNK_USE_CACHE config option
3766
0
    std::unique_ptr<CPLConfigOptionSetter> poVSIKERCHUNK_USE_CACHESetter;
3767
0
    if (CPLFetchBool(papszOpenOptions, "CACHE_KERCHUNK_JSON", false))
3768
0
    {
3769
0
        poVSIKERCHUNK_USE_CACHESetter = std::make_unique<CPLConfigOptionSetter>(
3770
0
            "VSIKERCHUNK_USE_CACHE", "YES", false);
3771
0
    }
3772
3773
    // Do some sanity checks on incompatible flags with thread-safe mode.
3774
0
    if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3775
0
    {
3776
0
        const struct
3777
0
        {
3778
0
            int nFlag;
3779
0
            const char *pszFlagName;
3780
0
        } asFlags[] = {
3781
0
            {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"},
3782
0
            {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"},
3783
0
            {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"},
3784
0
            {GDAL_OF_GNM, "GDAL_OF_GNM"},
3785
0
        };
3786
3787
0
        for (const auto &asFlag : asFlags)
3788
0
        {
3789
0
            if ((nOpenFlags & asFlag.nFlag) != 0)
3790
0
            {
3791
0
                CPLError(CE_Failure, CPLE_IllegalArg,
3792
0
                         "GDAL_OF_THREAD_SAFE and %s are mutually "
3793
0
                         "exclusive",
3794
0
                         asFlag.pszFlagName);
3795
0
                return nullptr;
3796
0
            }
3797
0
        }
3798
0
    }
3799
3800
    // If no driver kind is specified, assume all are to be probed.
3801
0
    if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3802
0
        nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3803
3804
    /* -------------------------------------------------------------------- */
3805
    /*      In case of shared dataset, first scan the existing list to see  */
3806
    /*      if it could already contain the requested dataset.              */
3807
    /* -------------------------------------------------------------------- */
3808
0
    if (nOpenFlags & GDAL_OF_SHARED)
3809
0
    {
3810
0
        if (nOpenFlags & GDAL_OF_INTERNAL)
3811
0
        {
3812
0
            CPLError(CE_Failure, CPLE_IllegalArg,
3813
0
                     "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3814
0
            return nullptr;
3815
0
        }
3816
3817
0
        auto poSharedDS =
3818
0
            GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
3819
0
        if (poSharedDS)
3820
0
        {
3821
0
            poSharedDS->Reference();
3822
0
            return poSharedDS;
3823
0
        }
3824
0
    }
3825
3826
0
    GDALDriverManager *poDM = GetGDALDriverManager();
3827
    // CPLLocaleC  oLocaleForcer;
3828
3829
0
    CPLErrorReset();
3830
0
    VSIErrorReset();
3831
0
    CPLAssert(nullptr != poDM);
3832
3833
    // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3834
    // shared dataset was asked before.
3835
0
    GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3836
0
                           const_cast<char **>(papszSiblingFiles));
3837
0
    oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3838
3839
0
    GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3840
0
    if (sAntiRecursion.nRecLevel == 100)
3841
0
    {
3842
0
        CPLError(CE_Failure, CPLE_AppDefined,
3843
0
                 "GDALOpen() called with too many recursion levels");
3844
0
        return nullptr;
3845
0
    }
3846
3847
0
    std::string osAllowedDrivers;
3848
0
    for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
3849
0
        osAllowedDrivers += pszDriverName;
3850
0
    auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
3851
0
        std::string(pszFilename), nOpenFlags, osAllowedDrivers);
3852
0
    if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))
3853
0
    {
3854
0
        CPLError(CE_Failure, CPLE_AppDefined,
3855
0
                 "GDALOpen() called on %s recursively", pszFilename);
3856
0
        return nullptr;
3857
0
    }
3858
3859
    // Remove leading @ if present.
3860
0
    char **papszOpenOptionsCleaned =
3861
0
        CSLDuplicate(const_cast<char **>(papszOpenOptions));
3862
0
    for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3863
0
         ++papszIter)
3864
0
    {
3865
0
        char *pszOption = *papszIter;
3866
0
        if (pszOption[0] == '@')
3867
0
            memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3868
0
    }
3869
3870
0
    oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3871
0
    oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
3872
3873
0
#ifdef OGRAPISPY_ENABLED
3874
0
    const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3875
0
    const int iSnapshot =
3876
0
        (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
3877
0
            ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
3878
0
            : INT_MIN;
3879
0
#endif
3880
3881
0
    const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
3882
0
    GDALDriver *poMissingPluginDriver = nullptr;
3883
0
    std::vector<GDALDriver *> apoSecondPassDrivers;
3884
3885
    // Lookup of matching driver for dataset can involve up to 2 passes:
3886
    // - in the first pass, all drivers that are compabile of the request mode
3887
    //   (raster/vector/etc.) are probed using their Identify() method if it
3888
    //   exists. If the Identify() method returns FALSE, the driver is skipped.
3889
    //   If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
3890
    //   driver is a deferred-loading plugin, it is added to the
3891
    //   apoSecondPassDrivers list for potential later probing, and execution
3892
    //   continues to the next driver in the list.
3893
    //   Otherwise if Identify() returns non-FALSE, the Open() method is used.
3894
    //   If Open() returns a non-NULL dataset, the loop stops and it is
3895
    //   returned. Otherwise looping over remaining drivers continues.
3896
    // - the second pass is optional, only if at least one driver was added
3897
    //   into apoSecondPassDrivers during the first pass. It is similar
3898
    //   to the first pass except it runs only on apoSecondPassDrivers drivers.
3899
    //   And the Open() method of such drivers is used, causing them to be
3900
    //   loaded for real.
3901
0
    int iPass = 1;
3902
0
retry:
3903
0
    for (int iDriver = 0;
3904
0
         iDriver < (iPass == 1 ? nDriverCount
3905
0
                               : static_cast<int>(apoSecondPassDrivers.size()));
3906
0
         ++iDriver)
3907
0
    {
3908
0
        GDALDriver *poDriver =
3909
0
            iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
3910
0
                       : apoSecondPassDrivers[iDriver];
3911
0
        if (papszAllowedDrivers != nullptr &&
3912
0
            CSLFindString(papszAllowedDrivers,
3913
0
                          GDALGetDriverShortName(poDriver)) == -1)
3914
0
        {
3915
0
            continue;
3916
0
        }
3917
3918
0
        if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
3919
0
            continue;
3920
3921
0
        if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
3922
0
            (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3923
0
            poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
3924
0
            continue;
3925
0
        if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3926
0
            (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3927
0
            poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
3928
0
            continue;
3929
0
        if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3930
0
            (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3931
0
            poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
3932
0
            continue;
3933
3934
        // Remove general OVERVIEW_LEVEL open options from list before passing
3935
        // it to the driver, if it isn't a driver specific option already.
3936
0
        char **papszTmpOpenOptions = nullptr;
3937
0
        char **papszTmpOpenOptionsToValidate = nullptr;
3938
0
        char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3939
0
        if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3940
0
                nullptr &&
3941
0
            !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3942
0
        {
3943
0
            papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3944
0
            papszTmpOpenOptions =
3945
0
                CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3946
0
            oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3947
3948
0
            papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3949
0
            papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
3950
0
                                                     "OVERVIEW_LEVEL", nullptr);
3951
0
            papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3952
0
        }
3953
3954
0
        const int nIdentifyRes =
3955
0
            poDriver->pfnIdentifyEx
3956
0
                ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
3957
0
            : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
3958
0
                                    : GDAL_IDENTIFY_UNKNOWN;
3959
0
        if (nIdentifyRes == FALSE)
3960
0
        {
3961
0
            CSLDestroy(papszTmpOpenOptions);
3962
0
            CSLDestroy(papszTmpOpenOptionsToValidate);
3963
0
            oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3964
0
            continue;
3965
0
        }
3966
0
        else if (iPass == 1 && nIdentifyRes < 0 &&
3967
0
                 poDriver->pfnOpen == nullptr &&
3968
0
                 poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
3969
0
        {
3970
            // Not loaded plugin
3971
0
            apoSecondPassDrivers.push_back(poDriver);
3972
0
            CSLDestroy(papszTmpOpenOptions);
3973
0
            CSLDestroy(papszTmpOpenOptionsToValidate);
3974
0
            oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3975
0
            continue;
3976
0
        }
3977
3978
0
        const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
3979
0
        if (bIdentifyRes)
3980
0
        {
3981
0
            GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3982
0
        }
3983
3984
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3985
0
        const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3986
0
        CPLErrorReset();
3987
0
#endif
3988
3989
0
        sAntiRecursion.nRecLevel++;
3990
0
        sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3991
3992
0
        GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
3993
3994
0
        sAntiRecursion.nRecLevel--;
3995
0
        sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3996
3997
0
        if (poDriver->pfnOpen != nullptr)
3998
0
        {
3999
            // If we couldn't determine for sure with Identify() (it returned
4000
            // -1), but Open() managed to open the file, post validate options.
4001
0
            if (poDS != nullptr &&
4002
0
                (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
4003
0
                !bIdentifyRes)
4004
0
            {
4005
0
                GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
4006
0
            }
4007
0
        }
4008
0
        else if (poDriver->pfnOpenWithDriverArg != nullptr)
4009
0
        {
4010
            // do nothing
4011
0
        }
4012
0
        else if (bIdentifyRes &&
4013
0
                 poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
4014
0
        {
4015
0
            if (!poMissingPluginDriver)
4016
0
            {
4017
0
                poMissingPluginDriver = poDriver;
4018
0
            }
4019
0
        }
4020
0
        else
4021
0
        {
4022
            // should not happen given the GDAL_DCAP_OPEN check
4023
0
            CSLDestroy(papszTmpOpenOptions);
4024
0
            CSLDestroy(papszTmpOpenOptionsToValidate);
4025
0
            oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4026
0
            continue;
4027
0
        }
4028
4029
0
        CSLDestroy(papszTmpOpenOptions);
4030
0
        CSLDestroy(papszTmpOpenOptionsToValidate);
4031
0
        oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
4032
4033
0
        if (poDS != nullptr)
4034
0
        {
4035
0
            if (poDS->papszOpenOptions == nullptr)
4036
0
            {
4037
0
                poDS->papszOpenOptions = papszOpenOptionsCleaned;
4038
0
                papszOpenOptionsCleaned = nullptr;
4039
0
            }
4040
4041
            // Deal with generic OVERVIEW_LEVEL open option, unless it is
4042
            // driver specific.
4043
0
            if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
4044
0
                    nullptr &&
4045
0
                !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
4046
0
            {
4047
0
                CPLString osVal(
4048
0
                    CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
4049
0
                const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
4050
0
                const bool bThisLevelOnly =
4051
0
                    nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
4052
0
                GDALDataset *poOvrDS =
4053
0
                    GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
4054
0
                if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
4055
0
                {
4056
0
                    if (strcmp(pszFilename, poDS->GetDescription()) != 0)
4057
0
                    {
4058
0
                        CPLError(
4059
0
                            CE_Warning, CPLE_NotSupported,
4060
0
                            "A dataset opened by GDALOpenShared should have "
4061
0
                            "the same filename (%s) "
4062
0
                            "and description (%s)",
4063
0
                            pszFilename, poDS->GetDescription());
4064
0
                    }
4065
0
                    else
4066
0
                    {
4067
0
                        CSLDestroy(poDS->papszOpenOptions);
4068
0
                        poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
4069
0
                        poDS->papszOpenOptions = CSLSetNameValue(
4070
0
                            poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
4071
0
                    }
4072
0
                }
4073
0
                poDS->ReleaseRef();
4074
0
                poDS = poOvrDS;
4075
0
                if (poDS == nullptr)
4076
0
                {
4077
0
                    if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4078
0
                    {
4079
0
                        CPLError(CE_Failure, CPLE_OpenFailed,
4080
0
                                 "Cannot open overview level %d of %s",
4081
0
                                 nOvrLevel, pszFilename);
4082
0
                    }
4083
0
                }
4084
0
                else
4085
0
                {
4086
                    // For thread-safe opening, currently poDS is what will be
4087
                    // the "master" dataset owned by the thread-safe dataset
4088
                    // returned to the user, hence we do not register it as a
4089
                    // visible one in the open dataset list, or mark it as shared.
4090
0
                    if (!(nOpenFlags & GDAL_OF_INTERNAL) &&
4091
0
                        !(nOpenFlags & GDAL_OF_THREAD_SAFE))
4092
0
                    {
4093
0
                        poDS->AddToDatasetOpenList();
4094
0
                    }
4095
0
                    if (nOpenFlags & GDAL_OF_SHARED)
4096
0
                    {
4097
0
                        CSLDestroy(poDS->papszOpenOptions);
4098
0
                        poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
4099
0
                        poDS->nOpenFlags = nOpenFlags;
4100
0
                        if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
4101
0
                            poDS->MarkAsShared();
4102
0
                    }
4103
0
                }
4104
0
            }
4105
0
            else if (nOpenFlags & GDAL_OF_SHARED)
4106
0
            {
4107
0
                if (strcmp(pszFilename, poDS->GetDescription()) != 0)
4108
0
                {
4109
0
                    CPLError(CE_Warning, CPLE_NotSupported,
4110
0
                             "A dataset opened by GDALOpenShared should have "
4111
0
                             "the same filename (%s) "
4112
0
                             "and description (%s)",
4113
0
                             pszFilename, poDS->GetDescription());
4114
0
                }
4115
0
                else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
4116
0
                {
4117
                    // For thread-safe opening, currently poDS is what will be
4118
                    // the "master" dataset owned by the thread-safe dataset
4119
                    // returned to the user, hence we do not or mark it as shared.
4120
0
                    poDS->MarkAsShared();
4121
0
                }
4122
0
            }
4123
4124
0
            VSIErrorReset();
4125
4126
0
            CSLDestroy(papszOpenOptionsCleaned);
4127
4128
0
#ifdef OGRAPISPY_ENABLED
4129
0
            if (iSnapshot != INT_MIN)
4130
0
            {
4131
0
                GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
4132
0
                OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4133
0
                poDS = GDALDataset::FromHandle(hDS);
4134
0
            }
4135
0
#endif
4136
4137
0
            if (poDS)
4138
0
            {
4139
0
                poDS->m_bCanBeReopened = true;
4140
4141
0
                if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
4142
0
                {
4143
0
                    poDS =
4144
0
                        GDALGetThreadSafeDataset(
4145
0
                            std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)
4146
0
                            .release();
4147
0
                    if (poDS)
4148
0
                    {
4149
0
                        poDS->m_bCanBeReopened = true;
4150
0
                        poDS->poDriver = poDriver;
4151
0
                        poDS->nOpenFlags = nOpenFlags;
4152
0
                        if (!(nOpenFlags & GDAL_OF_INTERNAL))
4153
0
                            poDS->AddToDatasetOpenList();
4154
0
                        if (nOpenFlags & GDAL_OF_SHARED)
4155
0
                            poDS->MarkAsShared();
4156
0
                    }
4157
0
                }
4158
0
            }
4159
4160
0
            return poDS;
4161
0
        }
4162
4163
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4164
0
        if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
4165
0
        {
4166
            // In case the file descriptor was "consumed" by a driver
4167
            // that ultimately failed, re-open it for next drivers.
4168
0
            oOpenInfo.fpL = VSIFOpenL(
4169
0
                pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
4170
0
        }
4171
#else
4172
        if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
4173
        {
4174
            CSLDestroy(papszOpenOptionsCleaned);
4175
4176
#ifdef OGRAPISPY_ENABLED
4177
            if (iSnapshot != INT_MIN)
4178
            {
4179
                GDALDatasetH hDS = nullptr;
4180
                OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4181
            }
4182
#endif
4183
            return nullptr;
4184
        }
4185
#endif
4186
0
    }
4187
4188
    // cppcheck-suppress knownConditionTrueFalse
4189
0
    if (iPass == 1 && !apoSecondPassDrivers.empty())
4190
0
    {
4191
0
        CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
4192
0
        iPass = 2;
4193
0
        goto retry;
4194
0
    }
4195
4196
0
    CSLDestroy(papszOpenOptionsCleaned);
4197
4198
0
#ifdef OGRAPISPY_ENABLED
4199
0
    if (iSnapshot != INT_MIN)
4200
0
    {
4201
0
        GDALDatasetH hDS = nullptr;
4202
0
        OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4203
0
    }
4204
0
#endif
4205
4206
0
    if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4207
0
    {
4208
0
        if (nDriverCount == 0)
4209
0
        {
4210
0
            CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
4211
0
        }
4212
0
        else if (poMissingPluginDriver)
4213
0
        {
4214
0
            std::string osMsg("`");
4215
0
            osMsg += pszFilename;
4216
0
            osMsg += "' not recognized as being in a supported file format. "
4217
0
                     "It could have been recognized by driver ";
4218
0
            osMsg += poMissingPluginDriver->GetDescription();
4219
0
            osMsg += ", but plugin ";
4220
0
            osMsg +=
4221
0
                GDALGetMessageAboutMissingPluginDriver(poMissingPluginDriver);
4222
4223
0
            CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
4224
0
        }
4225
        // Check to see if there was a filesystem error, and report it if so.
4226
        // If not, return a more generic error.
4227
0
        else if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
4228
0
        {
4229
0
            if (oOpenInfo.bStatOK)
4230
0
            {
4231
0
                CPLError(CE_Failure, CPLE_OpenFailed,
4232
0
                         "`%s' not recognized as being in a supported file "
4233
0
                         "format.",
4234
0
                         pszFilename);
4235
0
            }
4236
0
            else
4237
0
            {
4238
                // If Stat failed and no VSI error was set, assume it is because
4239
                // the file did not exist on the filesystem.
4240
0
                CPLError(CE_Failure, CPLE_OpenFailed,
4241
0
                         "`%s' does not exist in the file system, "
4242
0
                         "and is not recognized as a supported dataset name.",
4243
0
                         pszFilename);
4244
0
            }
4245
0
        }
4246
0
    }
4247
4248
0
    return nullptr;
4249
0
}
4250
4251
/************************************************************************/
4252
/*                           GDALOpenShared()                           */
4253
/************************************************************************/
4254
4255
/**
4256
 * \brief Open a raster file as a GDALDataset.
4257
 *
4258
 * This function works the same as GDALOpen(), but allows the sharing of
4259
 * GDALDataset handles for a dataset with other callers to GDALOpenShared().
4260
 *
4261
 * In particular, GDALOpenShared() will first consult its list of currently
4262
 * open and shared GDALDataset's, and if the GetDescription() name for one
4263
 * exactly matches the pszFilename passed to GDALOpenShared() it will be
4264
 * referenced and returned.
4265
 *
4266
 * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
4267
 * pszFilename from two different threads, a different GDALDataset object will
4268
 * be returned as it is not safe to use the same dataset from different threads,
4269
 * unless the user does explicitly use mutexes in its code.
4270
 *
4271
 * For drivers supporting the VSI virtual file API, it is possible to open a
4272
 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
4273
 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
4274
 * server (see VSIInstallCurlFileHandler())
4275
 *
4276
 * \sa GDALOpen()
4277
 * \sa GDALOpenEx()
4278
 *
4279
 * @param pszFilename the name of the file to access.  In the case of
4280
 * exotic drivers this may not refer to a physical file, but instead contain
4281
 * information for the driver on how to access a dataset.  It should be in
4282
 * UTF-8 encoding.
4283
 *
4284
 * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
4285
 * drivers support only read only access.
4286
 *
4287
 * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
4288
 * this handle can be cast to a GDALDataset *.
4289
 */
4290
4291
GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4292
                                        GDALAccess eAccess)
4293
0
{
4294
0
    VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4295
0
    return GDALOpenEx(pszFilename,
4296
0
                      GDAL_OF_RASTER |
4297
0
                          (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4298
0
                          GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4299
0
                      nullptr, nullptr, nullptr);
4300
0
}
4301
4302
/************************************************************************/
4303
/*                             GDALClose()                              */
4304
/************************************************************************/
4305
4306
/**
4307
 * \brief Close GDAL dataset.
4308
 *
4309
 * For non-shared datasets (opened with GDALOpen()) the dataset is closed
4310
 * using the C++ "delete" operator, recovering all dataset related resources.
4311
 * For shared datasets (opened with GDALOpenShared()) the dataset is
4312
 * dereferenced, and closed only if the referenced count has dropped below 1.
4313
 *
4314
 * @param hDS The dataset to close.  May be cast from a "GDALDataset *".
4315
 * @return CE_None in case of success (return value since GDAL 3.7). On a
4316
 * shared dataset whose reference count is not dropped below 1, CE_None will
4317
 * be returned.
4318
 */
4319
4320
CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4321
4322
0
{
4323
0
    if (!hDS)
4324
0
        return CE_None;
4325
4326
0
#ifdef OGRAPISPY_ENABLED
4327
0
    if (bOGRAPISpyEnabled)
4328
0
        OGRAPISpyPreClose(hDS);
4329
0
#endif
4330
4331
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4332
4333
0
    if (poDS->GetShared())
4334
0
    {
4335
        /* --------------------------------------------------------------------
4336
         */
4337
        /*      If this file is in the shared dataset list then dereference */
4338
        /*      it, and only delete/remote it if the reference count has */
4339
        /*      dropped to zero. */
4340
        /* --------------------------------------------------------------------
4341
         */
4342
0
        if (poDS->Dereference() > 0)
4343
0
            return CE_None;
4344
4345
0
        CPLErr eErr = poDS->Close();
4346
0
        delete poDS;
4347
4348
0
#ifdef OGRAPISPY_ENABLED
4349
0
        if (bOGRAPISpyEnabled)
4350
0
            OGRAPISpyPostClose();
4351
0
#endif
4352
4353
0
        return eErr;
4354
0
    }
4355
4356
    /* -------------------------------------------------------------------- */
4357
    /*      This is not shared dataset, so directly delete it.              */
4358
    /* -------------------------------------------------------------------- */
4359
0
    CPLErr eErr = poDS->Close();
4360
0
    delete poDS;
4361
4362
0
#ifdef OGRAPISPY_ENABLED
4363
0
    if (bOGRAPISpyEnabled)
4364
0
        OGRAPISpyPostClose();
4365
0
#endif
4366
0
    return eErr;
4367
0
}
4368
4369
/************************************************************************/
4370
/*                        GDALDumpOpenDataset()                         */
4371
/************************************************************************/
4372
4373
static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
4374
0
{
4375
0
    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
4376
0
    FILE *fp = static_cast<FILE *>(user_data);
4377
0
    GDALDataset *poDS = psStruct->poDS;
4378
4379
0
    const char *pszDriverName = poDS->GetDriver() == nullptr
4380
0
                                    ? "DriverIsNULL"
4381
0
                                    : poDS->GetDriver()->GetDescription();
4382
4383
0
    poDS->Reference();
4384
0
    CPL_IGNORE_RET_VAL(
4385
0
        VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4386
0
                   poDS->GetShared() ? 'S' : 'N', pszDriverName,
4387
0
                   static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
4388
0
                   poDS->GetRasterYSize(), poDS->GetRasterCount(),
4389
0
                   poDS->GetDescription()));
4390
4391
0
    return TRUE;
4392
0
}
4393
4394
static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
4395
0
{
4396
4397
    // Don't list shared datasets. They have already been listed by
4398
    // GDALDumpOpenSharedDatasetsForeach.
4399
0
    if (poDS->GetShared())
4400
0
        return TRUE;
4401
4402
0
    const char *pszDriverName = poDS->GetDriver() == nullptr
4403
0
                                    ? "DriverIsNULL"
4404
0
                                    : poDS->GetDriver()->GetDescription();
4405
4406
0
    poDS->Reference();
4407
0
    CPL_IGNORE_RET_VAL(
4408
0
        VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4409
0
                   poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
4410
0
                   poDS->GetRasterXSize(), poDS->GetRasterYSize(),
4411
0
                   poDS->GetRasterCount(), poDS->GetDescription()));
4412
4413
0
    return TRUE;
4414
0
}
4415
4416
/**
4417
 * \brief List open datasets.
4418
 *
4419
 * Dumps a list of all open datasets (shared or not) to the indicated
4420
 * text file (may be stdout or stderr).   This function is primarily intended
4421
 * to assist in debugging "dataset leaks" and reference counting issues.
4422
 * The information reported includes the dataset name, referenced count,
4423
 * shared status, driver name, size, and band count.
4424
 */
4425
4426
int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
4427
4428
0
{
4429
0
    VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
4430
4431
0
    CPLMutexHolderD(&hDLMutex);
4432
4433
0
    if (poAllDatasetMap == nullptr)
4434
0
        return 0;
4435
4436
0
    CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
4437
4438
0
    for (const auto &oIter : *poAllDatasetMap)
4439
0
    {
4440
0
        GDALDumpOpenDatasetsForeach(oIter.first, fp);
4441
0
    }
4442
4443
0
    if (phSharedDatasetSet != nullptr)
4444
0
    {
4445
0
        CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
4446
0
                          fp);
4447
0
    }
4448
0
    return static_cast<int>(poAllDatasetMap->size());
4449
0
}
4450
4451
/************************************************************************/
4452
/*                        BeginAsyncReader()                            */
4453
/************************************************************************/
4454
4455
/**
4456
 * \brief Sets up an asynchronous data request
4457
 *
4458
 * This method establish an asynchronous raster read request for the
4459
 * indicated window on the dataset into the indicated buffer.  The parameters
4460
 * for windowing, buffer size, buffer type and buffer organization are similar
4461
 * to those for GDALDataset::RasterIO(); however, this call only launches
4462
 * the request and filling the buffer is accomplished via calls to
4463
 * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4464
 *
4465
 * Once all processing for the created session is complete, or if no further
4466
 * refinement of the request is required, the GDALAsyncReader object should
4467
 * be destroyed with the GDALDataset::EndAsyncReader() method.
4468
 *
4469
 * Note that the data buffer (pData) will potentially continue to be
4470
 * updated as long as the session lives, but it is not deallocated when
4471
 * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
4472
 * should be deallocated by the application at that point.
4473
 *
4474
 * Additional information on asynchronous IO in GDAL may be found at:
4475
 *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4476
 *
4477
 * This method is the same as the C GDALBeginAsyncReader() function.
4478
 *
4479
 * @param nXOff The pixel offset to the top left corner of the region
4480
 * of the band to be accessed.  This would be zero to start from the left side.
4481
 *
4482
 * @param nYOff The line offset to the top left corner of the region
4483
 * of the band to be accessed.  This would be zero to start from the top.
4484
 *
4485
 * @param nXSize The width of the region of the band to be accessed in pixels.
4486
 *
4487
 * @param nYSize The height of the region of the band to be accessed in lines.
4488
 *
4489
 * @param pBuf The buffer into which the data should be read. This buffer must
4490
 * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4491
 * It is organized in left to right,top to bottom pixel order.  Spacing is
4492
 * controlled by the nPixelSpace, and nLineSpace parameters.
4493
 *
4494
 * @param nBufXSize the width of the buffer image into which the desired region
4495
 * is to be read, or from which it is to be written.
4496
 *
4497
 * @param nBufYSize the height of the buffer image into which the desired
4498
 * region is to be read, or from which it is to be written.
4499
 *
4500
 * @param eBufType the type of the pixel values in the pData data buffer.  The
4501
 * pixel values will automatically be translated to/from the GDALRasterBand
4502
 * data type as needed.
4503
 *
4504
 * @param nBandCount the number of bands being read or written.
4505
 *
4506
 * @param panBandMap the list of nBandCount band numbers being read/written.
4507
 * Note band numbers are 1 based.   This may be NULL to select the first
4508
 * nBandCount bands.
4509
 *
4510
 * @param nPixelSpace The byte offset from the start of one pixel value in
4511
 * pData to the start of the next pixel value within a scanline.  If defaulted
4512
 * (0) the size of the datatype eBufType is used.
4513
 *
4514
 * @param nLineSpace The byte offset from the start of one scanline in
4515
 * pData to the start of the next.  If defaulted the size of the datatype
4516
 * eBufType * nBufXSize is used.
4517
 *
4518
 * @param nBandSpace the byte offset from the start of one bands data to the
4519
 * start of the next.  If defaulted (zero) the value will be
4520
 * nLineSpace * nBufYSize implying band sequential organization
4521
 * of the data buffer.
4522
 *
4523
 * @param papszOptions Driver specific control options in a string list or NULL.
4524
 * Consult driver documentation for options supported.
4525
 *
4526
 * @return The GDALAsyncReader object representing the request.
4527
 */
4528
4529
GDALAsyncReader *GDALDataset::BeginAsyncReader(
4530
    int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
4531
    int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
4532
    int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
4533
0
{
4534
    // See gdaldefaultasync.cpp
4535
4536
0
    return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
4537
0
                                     nBufXSize, nBufYSize, eBufType, nBandCount,
4538
0
                                     panBandMap, nPixelSpace, nLineSpace,
4539
0
                                     nBandSpace, papszOptions);
4540
0
}
4541
4542
/************************************************************************/
4543
/*                        GDALBeginAsyncReader()                      */
4544
/************************************************************************/
4545
4546
/**
4547
 * \brief Sets up an asynchronous data request
4548
 *
4549
 * This method establish an asynchronous raster read request for the
4550
 * indicated window on the dataset into the indicated buffer.  The parameters
4551
 * for windowing, buffer size, buffer type and buffer organization are similar
4552
 * to those for GDALDataset::RasterIO(); however, this call only launches
4553
 * the request and filling the buffer is accomplished via calls to
4554
 * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4555
 *
4556
 * Once all processing for the created session is complete, or if no further
4557
 * refinement of the request is required, the GDALAsyncReader object should
4558
 * be destroyed with the GDALDataset::EndAsyncReader() method.
4559
 *
4560
 * Note that the data buffer (pData) will potentially continue to be
4561
 * updated as long as the session lives, but it is not deallocated when
4562
 * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
4563
 * should be deallocated by the application at that point.
4564
 *
4565
 * Additional information on asynchronous IO in GDAL may be found at:
4566
 *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4567
 *
4568
 * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
4569
 *
4570
 * @param hDS handle to the dataset object.
4571
 *
4572
 * @param nXOff The pixel offset to the top left corner of the region
4573
 * of the band to be accessed.  This would be zero to start from the left side.
4574
 *
4575
 * @param nYOff The line offset to the top left corner of the region
4576
 * of the band to be accessed.  This would be zero to start from the top.
4577
 *
4578
 * @param nXSize The width of the region of the band to be accessed in pixels.
4579
 *
4580
 * @param nYSize The height of the region of the band to be accessed in lines.
4581
 *
4582
 * @param pBuf The buffer into which the data should be read. This buffer must
4583
 * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4584
 * It is organized in left to right,top to bottom pixel order.  Spacing is
4585
 * controlled by the nPixelSpace, and nLineSpace parameters.
4586
 *
4587
 * @param nBufXSize the width of the buffer image into which the desired region
4588
 * is to be read, or from which it is to be written.
4589
 *
4590
 * @param nBufYSize the height of the buffer image into which the desired
4591
 * region is to be read, or from which it is to be written.
4592
 *
4593
 * @param eBufType the type of the pixel values in the pData data buffer.  The
4594
 * pixel values will automatically be translated to/from the GDALRasterBand
4595
 * data type as needed.
4596
 *
4597
 * @param nBandCount the number of bands being read or written.
4598
 *
4599
 * @param panBandMap the list of nBandCount band numbers being read/written.
4600
 * Note band numbers are 1 based.   This may be NULL to select the first
4601
 * nBandCount bands.
4602
 *
4603
 * @param nPixelSpace The byte offset from the start of one pixel value in
4604
 * pData to the start of the next pixel value within a scanline.  If defaulted
4605
 * (0) the size of the datatype eBufType is used.
4606
 *
4607
 * @param nLineSpace The byte offset from the start of one scanline in
4608
 * pData to the start of the next.  If defaulted the size of the datatype
4609
 * eBufType * nBufXSize is used.
4610
 *
4611
 * @param nBandSpace the byte offset from the start of one bands data to the
4612
 * start of the next.  If defaulted (zero) the value will be
4613
 * nLineSpace * nBufYSize implying band sequential organization
4614
 * of the data buffer.
4615
 *
4616
 * @param papszOptions Driver specific control options in a string list or NULL.
4617
 * Consult driver documentation for options supported.
4618
 *
4619
 * @return handle representing the request.
4620
 */
4621
4622
GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
4623
    GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
4624
    int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
4625
    int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
4626
    CSLConstList papszOptions)
4627
4628
0
{
4629
0
    VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
4630
0
    return static_cast<GDALAsyncReaderH>(
4631
0
        GDALDataset::FromHandle(hDS)->BeginAsyncReader(
4632
0
            nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
4633
0
            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
4634
0
            const_cast<char **>(papszOptions)));
4635
0
}
4636
4637
/************************************************************************/
4638
/*                        EndAsyncReader()                            */
4639
/************************************************************************/
4640
4641
/**
4642
 * End asynchronous request.
4643
 *
4644
 * This method destroys an asynchronous io request and recovers all
4645
 * resources associated with it.
4646
 *
4647
 * This method is the same as the C function GDALEndAsyncReader().
4648
 *
4649
 * @param poARIO pointer to a GDALAsyncReader
4650
 */
4651
4652
void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
4653
0
{
4654
0
    delete poARIO;
4655
0
}
4656
4657
/************************************************************************/
4658
/*                        GDALEndAsyncReader()                        */
4659
/************************************************************************/
4660
4661
/**
4662
 * End asynchronous request.
4663
 *
4664
 * This method destroys an asynchronous io request and recovers all
4665
 * resources associated with it.
4666
 *
4667
 * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4668
 *
4669
 * @param hDS handle to the dataset object.
4670
 * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4671
 */
4672
4673
void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
4674
                                    GDALAsyncReaderH hAsyncReaderH)
4675
0
{
4676
0
    VALIDATE_POINTER0(hDS, "GDALDataset");
4677
0
    VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4678
0
    GDALDataset::FromHandle(hDS)->EndAsyncReader(
4679
0
        static_cast<GDALAsyncReader *>(hAsyncReaderH));
4680
0
}
4681
4682
/************************************************************************/
4683
/*                       CloseDependentDatasets()                       */
4684
/************************************************************************/
4685
4686
/**
4687
 * Drop references to any other datasets referenced by this dataset.
4688
 *
4689
 * This method should release any reference to other datasets (e.g. a VRT
4690
 * dataset to its sources), but not close the current dataset itself.
4691
 *
4692
 * If at least, one reference to a dependent dataset has been dropped,
4693
 * this method should return TRUE. Otherwise it *should* return FALSE.
4694
 * (Failure to return the proper value might result in infinite loop)
4695
 *
4696
 * This method can be called several times on a given dataset. After
4697
 * the first time, it should not do anything and return FALSE.
4698
 *
4699
 * The driver implementation may choose to destroy its raster bands,
4700
 * so be careful not to call any method on the raster bands afterwards.
4701
 *
4702
 * Basically the only safe action you can do after calling
4703
 * CloseDependentDatasets() is to call the destructor.
4704
 *
4705
 * Note: the only legitimate caller of CloseDependentDatasets() is
4706
 * GDALDriverManager::~GDALDriverManager()
4707
 *
4708
 * @return TRUE if at least one reference to another dataset has been dropped.
4709
 */
4710
int GDALDataset::CloseDependentDatasets()
4711
0
{
4712
0
    return oOvManager.CloseDependentDatasets();
4713
0
}
4714
4715
/************************************************************************/
4716
/*                            ReportError()                             */
4717
/************************************************************************/
4718
4719
#ifndef DOXYGEN_XML
4720
/**
4721
 * \brief Emits an error related to a dataset.
4722
 *
4723
 * This function is a wrapper for regular CPLError(). The only difference
4724
 * with CPLError() is that it prepends the error message with the dataset
4725
 * name.
4726
 *
4727
 * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4728
 * @param err_no the error number (CPLE_*) from cpl_error.h.
4729
 * @param fmt a printf() style format string.  Any additional arguments
4730
 * will be treated as arguments to fill in this format in a manner
4731
 * similar to printf().
4732
 *
4733
 * @since GDAL 1.9.0
4734
 */
4735
4736
void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4737
                              const char *fmt, ...) const
4738
0
{
4739
0
    va_list args;
4740
0
    va_start(args, fmt);
4741
0
    ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4742
0
    va_end(args);
4743
0
}
4744
4745
/**
4746
 * \brief Emits an error related to a dataset (static method)
4747
 *
4748
 * This function is a wrapper for regular CPLError(). The only difference
4749
 * with CPLError() is that it prepends the error message with the dataset
4750
 * name.
4751
 *
4752
 * @param pszDSName dataset name.
4753
 * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4754
 * @param err_no the error number (CPLE_*) from cpl_error.h.
4755
 * @param fmt a printf() style format string.  Any additional arguments
4756
 * will be treated as arguments to fill in this format in a manner
4757
 * similar to printf().
4758
 *
4759
 * @since GDAL 3.2.0
4760
 */
4761
4762
void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4763
                              CPLErrorNum err_no, const char *fmt, ...)
4764
0
{
4765
0
    va_list args;
4766
0
    va_start(args, fmt);
4767
0
    ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4768
0
    va_end(args);
4769
0
}
4770
4771
void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4772
                               CPLErrorNum err_no, const char *fmt,
4773
                               va_list args)
4774
0
{
4775
0
    pszDSName = CPLGetFilename(pszDSName);
4776
0
    if (pszDSName[0] != '\0')
4777
0
    {
4778
0
        CPLError(eErrClass, err_no, "%s",
4779
0
                 std::string(pszDSName)
4780
0
                     .append(": ")
4781
0
                     .append(CPLString().vPrintf(fmt, args))
4782
0
                     .c_str());
4783
0
    }
4784
0
    else
4785
0
    {
4786
0
        CPLErrorV(eErrClass, err_no, fmt, args);
4787
0
    }
4788
0
}
4789
#endif
4790
4791
/************************************************************************/
4792
/*                            GetMetadata()                             */
4793
/************************************************************************/
4794
char **GDALDataset::GetMetadata(const char *pszDomain)
4795
0
{
4796
#ifndef WITHOUT_DERIVED
4797
    if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4798
    {
4799
        oDerivedMetadataList.Clear();
4800
4801
        // First condition: at least one raster band.
4802
        if (GetRasterCount() > 0)
4803
        {
4804
            // Check if there is at least one complex band.
4805
            bool hasAComplexBand = false;
4806
4807
            for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4808
            {
4809
                if (GDALDataTypeIsComplex(
4810
                        GetRasterBand(rasterId)->GetRasterDataType()))
4811
                {
4812
                    hasAComplexBand = true;
4813
                    break;
4814
                }
4815
            }
4816
4817
            unsigned int nbSupportedDerivedDS = 0;
4818
            const DerivedDatasetDescription *poDDSDesc =
4819
                GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4820
4821
            int nNumDataset = 1;
4822
            for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4823
                 ++derivedId)
4824
            {
4825
                if (hasAComplexBand ||
4826
                    CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4827
                        "complex")
4828
                {
4829
                    oDerivedMetadataList.SetNameValue(
4830
                        CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4831
                        CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4832
                                   poDDSDesc[derivedId].pszDatasetName,
4833
                                   GetDescription()));
4834
4835
                    CPLString osDesc(
4836
                        CPLSPrintf("%s from %s",
4837
                                   poDDSDesc[derivedId].pszDatasetDescription,
4838
                                   GetDescription()));
4839
                    oDerivedMetadataList.SetNameValue(
4840
                        CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4841
                        osDesc.c_str());
4842
4843
                    nNumDataset++;
4844
                }
4845
            }
4846
        }
4847
        return oDerivedMetadataList.List();
4848
    }
4849
#endif
4850
4851
0
    return GDALMajorObject::GetMetadata(pszDomain);
4852
0
}
4853
4854
// clang-format off
4855
4856
/**
4857
 * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4858
 * \brief Set metadata.
4859
 *
4860
 * CAUTION: depending on the format, older values of the updated information
4861
 * might still be found in the file in a "ghost" state, even if no longer
4862
 * accessible through the GDAL API. This is for example the case of the GTiff
4863
 * format (this is not a exhaustive list)
4864
 *
4865
 * The C function GDALSetMetadata() does the same thing as this method.
4866
 *
4867
 * @param papszMetadata the metadata in name=value string list format to
4868
 * apply.
4869
 * @param pszDomain the domain of interest.  Use "" or NULL for the default
4870
 * domain.
4871
 * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4872
 * metadata has been accepted, but is likely not maintained persistently
4873
 * by the underlying object between sessions.
4874
 */
4875
4876
/**
4877
 * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
4878
 * \brief Set single metadata item.
4879
 *
4880
 * CAUTION: depending on the format, older values of the updated information
4881
 * might still be found in the file in a "ghost" state, even if no longer
4882
 * accessible through the GDAL API. This is for example the case of the GTiff
4883
 * format (this is not a exhaustive list)
4884
 *
4885
 * The C function GDALSetMetadataItem() does the same thing as this method.
4886
 *
4887
 * @param pszName the key for the metadata item to fetch.
4888
 * @param pszValue the value to assign to the key.
4889
 * @param pszDomain the domain to set within, use NULL for the default domain.
4890
 *
4891
 * @return CE_None on success, or an error code on failure.
4892
 */
4893
4894
// clang-format on
4895
4896
/************************************************************************/
4897
/*                            GetMetadataDomainList()                   */
4898
/************************************************************************/
4899
4900
char **GDALDataset::GetMetadataDomainList()
4901
0
{
4902
0
    char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4903
4904
    // Ensure that we do not duplicate DERIVED domain.
4905
0
    if (GetRasterCount() > 0 &&
4906
0
        CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4907
0
    {
4908
0
        currentDomainList =
4909
0
            CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4910
0
    }
4911
0
    return currentDomainList;
4912
0
}
4913
4914
/************************************************************************/
4915
/*                            GetDriverName()                           */
4916
/************************************************************************/
4917
4918
/** Return driver name.
4919
 * @return driver name.
4920
 */
4921
const char *GDALDataset::GetDriverName()
4922
0
{
4923
0
    if (poDriver)
4924
0
        return poDriver->GetDescription();
4925
0
    return "";
4926
0
}
4927
4928
/************************************************************************/
4929
/*                     GDALDatasetReleaseResultSet()                    */
4930
/************************************************************************/
4931
4932
/**
4933
 \brief Release results of ExecuteSQL().
4934
4935
 This function should only be used to deallocate OGRLayers resulting from
4936
 an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
4937
 results set before destroying the GDALDataset may cause errors.
4938
4939
 This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4940
4941
 @since GDAL 2.0
4942
4943
 @param hDS the dataset handle.
4944
 @param hLayer the result of a previous ExecuteSQL() call.
4945
4946
*/
4947
void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
4948
4949
0
{
4950
0
    VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4951
4952
0
#ifdef OGRAPISPY_ENABLED
4953
0
    if (bOGRAPISpyEnabled)
4954
0
        OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4955
0
#endif
4956
4957
0
    GDALDataset::FromHandle(hDS)->ReleaseResultSet(
4958
0
        OGRLayer::FromHandle(hLayer));
4959
0
}
4960
4961
/************************************************************************/
4962
/*                       GDALDatasetGetLayerCount()                     */
4963
/************************************************************************/
4964
4965
/**
4966
 \brief Get the number of layers in this dataset.
4967
4968
 This function is the same as the C++ method GDALDataset::GetLayerCount()
4969
4970
 @since GDAL 2.0
4971
4972
 @param hDS the dataset handle.
4973
 @return layer count.
4974
*/
4975
4976
int GDALDatasetGetLayerCount(GDALDatasetH hDS)
4977
4978
0
{
4979
0
    VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4980
4981
0
#ifdef OGRAPISPY_ENABLED
4982
0
    if (bOGRAPISpyEnabled)
4983
0
        OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4984
0
#endif
4985
4986
0
    return GDALDataset::FromHandle(hDS)->GetLayerCount();
4987
0
}
4988
4989
/************************************************************************/
4990
/*                        GDALDatasetGetLayer()                         */
4991
/************************************************************************/
4992
4993
/**
4994
 \brief Fetch a layer by index.
4995
4996
 The returned layer remains owned by the
4997
 GDALDataset and should not be deleted by the application.
4998
4999
 This function is the same as the C++ method GDALDataset::GetLayer()
5000
5001
 @since GDAL 2.0
5002
5003
 @param hDS the dataset handle.
5004
 @param iLayer a layer number between 0 and GetLayerCount()-1.
5005
5006
 @return the layer, or NULL if iLayer is out of range or an error occurs.
5007
*/
5008
5009
OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
5010
5011
0
{
5012
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
5013
5014
0
    OGRLayerH hLayer =
5015
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
5016
5017
0
#ifdef OGRAPISPY_ENABLED
5018
0
    if (bOGRAPISpyEnabled)
5019
0
        OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
5020
0
#endif
5021
5022
0
    return hLayer;
5023
0
}
5024
5025
/************************************************************************/
5026
/*                     GDALDatasetGetLayerByName()                      */
5027
/************************************************************************/
5028
5029
/**
5030
 \brief Fetch a layer by name.
5031
5032
 The returned layer remains owned by the
5033
 GDALDataset and should not be deleted by the application.
5034
5035
 This function is the same as the C++ method GDALDataset::GetLayerByName()
5036
5037
 @since GDAL 2.0
5038
5039
 @param hDS the dataset handle.
5040
 @param pszName the layer name of the layer to fetch.
5041
5042
 @return the layer, or NULL if Layer is not found or an error occurs.
5043
*/
5044
5045
OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
5046
5047
0
{
5048
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
5049
5050
0
    OGRLayerH hLayer = OGRLayer::ToHandle(
5051
0
        GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
5052
5053
0
#ifdef OGRAPISPY_ENABLED
5054
0
    if (bOGRAPISpyEnabled)
5055
0
        OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
5056
0
#endif
5057
5058
0
    return hLayer;
5059
0
}
5060
5061
/************************************************************************/
5062
/*                        GDALDatasetIsLayerPrivate()                   */
5063
/************************************************************************/
5064
5065
/**
5066
 \brief Returns true if the layer at the specified index is deemed a private or
5067
 system table, or an internal detail only.
5068
5069
 This function is the same as the C++ method GDALDataset::IsLayerPrivate()
5070
5071
 @since GDAL 3.4
5072
5073
 @param hDS the dataset handle.
5074
 @param iLayer a layer number between 0 and GetLayerCount()-1.
5075
5076
 @return true if the layer is a private or system table.
5077
*/
5078
5079
int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
5080
5081
0
{
5082
0
    VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
5083
5084
0
    const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
5085
5086
0
    return res ? 1 : 0;
5087
0
}
5088
5089
/************************************************************************/
5090
/*                            GetLayerIndex()                           */
5091
/************************************************************************/
5092
5093
/**
5094
 \brief Returns the index of the layer specified by name.
5095
5096
 @since GDAL 3.12
5097
5098
 @param pszName layer name (not NULL)
5099
5100
 @return an index >= 0, or -1 if not found.
5101
*/
5102
5103
int GDALDataset::GetLayerIndex(const char *pszName)
5104
0
{
5105
0
    const int nLayerCount = GetLayerCount();
5106
0
    int iMatch = -1;
5107
0
    for (int i = 0; i < nLayerCount; ++i)
5108
0
    {
5109
0
        if (const auto poLayer = GetLayer(i))
5110
0
        {
5111
0
            const char *pszLayerName = poLayer->GetDescription();
5112
0
            if (strcmp(pszName, pszLayerName) == 0)
5113
0
            {
5114
0
                iMatch = i;
5115
0
                break;
5116
0
            }
5117
0
            else if (EQUAL(pszName, pszLayerName))
5118
0
            {
5119
0
                iMatch = i;
5120
0
            }
5121
0
        }
5122
0
    }
5123
0
    return iMatch;
5124
0
}
5125
5126
/************************************************************************/
5127
/*                        GDALDatasetDeleteLayer()                      */
5128
/************************************************************************/
5129
5130
/**
5131
 \brief Delete the indicated layer from the datasource.
5132
5133
 If this function is supported
5134
 the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
5135
5136
 This method is the same as the C++ method GDALDataset::DeleteLayer().
5137
5138
 @since GDAL 2.0
5139
5140
 @param hDS the dataset handle.
5141
 @param iLayer the index of the layer to delete.
5142
5143
 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
5144
 layers is not supported for this datasource.
5145
5146
*/
5147
OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
5148
5149
0
{
5150
0
    VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
5151
5152
0
#ifdef OGRAPISPY_ENABLED
5153
0
    if (bOGRAPISpyEnabled)
5154
0
        OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
5155
0
#endif
5156
5157
0
    return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
5158
0
}
5159
5160
/************************************************************************/
5161
/*                            CreateLayer()                             */
5162
/************************************************************************/
5163
5164
/**
5165
\brief This method attempts to create a new layer on the dataset with the
5166
indicated name, coordinate system, geometry type.
5167
5168
The papszOptions argument
5169
can be used to control driver specific creation options.  These options are
5170
normally documented in the format specific documentation.
5171
That function will try to validate the creation option list passed to the
5172
driver with the GDALValidateCreationOptions() method. This check can be
5173
disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5174
to NO.
5175
5176
Drivers should extend the ICreateLayer() method and not
5177
CreateLayer(). CreateLayer() adds validation of layer creation options, before
5178
delegating the actual work to ICreateLayer().
5179
5180
This method is the same as the C function GDALDatasetCreateLayer() and the
5181
deprecated OGR_DS_CreateLayer().
5182
5183
Example:
5184
5185
\code{.cpp}
5186
#include "gdal.h"
5187
#include "cpl_string.h"
5188
5189
...
5190
5191
        OGRLayer *poLayer;
5192
        char     **papszOptions;
5193
5194
        if( !poDS->TestCapability( ODsCCreateLayer ) )
5195
        {
5196
        ...
5197
        }
5198
5199
        papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5200
        poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
5201
                                     papszOptions );
5202
        CSLDestroy( papszOptions );
5203
5204
        if( poLayer == NULL )
5205
        {
5206
            ...
5207
        }
5208
\endcode
5209
5210
@param pszName the name for the new layer.  This should ideally not
5211
match any existing layer on the datasource.
5212
@param poSpatialRef the coordinate system to use for the new layer, or NULL if
5213
no coordinate system is available.
5214
@param eGType the geometry type for the layer.  Use wkbUnknown if there
5215
are no constraints on the types geometry to be written.
5216
@param papszOptions a StringList of name=value options.  Options are driver
5217
specific.
5218
5219
@return NULL is returned on failure, or a new OGRLayer handle on success.
5220
5221
*/
5222
5223
OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5224
                                   const OGRSpatialReference *poSpatialRef,
5225
                                   OGRwkbGeometryType eGType,
5226
                                   CSLConstList papszOptions)
5227
5228
0
{
5229
0
    if (eGType == wkbNone)
5230
0
    {
5231
0
        return CreateLayer(pszName, nullptr, papszOptions);
5232
0
    }
5233
0
    else
5234
0
    {
5235
0
        OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5236
0
        oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5237
0
        return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5238
0
    }
5239
0
}
5240
5241
/**
5242
\brief This method attempts to create a new layer on the dataset with the
5243
indicated name and geometry field definition.
5244
5245
When poGeomFieldDefn is not null, most drivers should honor
5246
poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5247
Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5248
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5249
poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5250
very few currently.
5251
5252
Note that even if a geometry coordinate precision is set and a driver honors the
5253
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5254
OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5255
with the coordinate precision. That is they are assumed to be valid once their
5256
coordinates are rounded to it. If it might not be the case, the user may set
5257
the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5258
or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5259
the passed geometries.
5260
5261
The papszOptions argument
5262
can be used to control driver specific creation options. These options are
5263
normally documented in the format specific documentation.
5264
This function will try to validate the creation option list passed to the
5265
driver with the GDALValidateCreationOptions() method. This check can be
5266
disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5267
to NO.
5268
5269
Drivers should extend the ICreateLayer() method and not
5270
CreateLayer(). CreateLayer() adds validation of layer creation options, before
5271
delegating the actual work to ICreateLayer().
5272
5273
This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5274
5275
@param pszName the name for the new layer.  This should ideally not
5276
match any existing layer on the datasource.
5277
@param poGeomFieldDefn the geometry field definition to use for the new layer,
5278
or NULL if there is no geometry field.
5279
@param papszOptions a StringList of name=value options.  Options are driver
5280
specific.
5281
5282
@return NULL is returned on failure, or a new OGRLayer handle on success.
5283
@since 3.9
5284
5285
*/
5286
5287
OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5288
                                   const OGRGeomFieldDefn *poGeomFieldDefn,
5289
                                   CSLConstList papszOptions)
5290
5291
0
{
5292
0
    if (CPLTestBool(
5293
0
            CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5294
0
    {
5295
0
        ValidateLayerCreationOptions(papszOptions);
5296
0
    }
5297
5298
0
    OGRLayer *poLayer;
5299
0
    if (poGeomFieldDefn)
5300
0
    {
5301
0
        OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5302
0
        if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5303
0
            !TestCapability(ODsCCurveGeometries))
5304
0
        {
5305
0
            oGeomFieldDefn.SetType(
5306
0
                OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5307
0
        }
5308
5309
0
        poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5310
0
    }
5311
0
    else
5312
0
    {
5313
0
        poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5314
0
    }
5315
0
#ifdef DEBUG
5316
0
    if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5317
0
        !poLayer->TestCapability(OLCCurveGeometries))
5318
0
    {
5319
0
        CPLError(CE_Warning, CPLE_AppDefined,
5320
0
                 "Inconsistent driver: Layer geometry type is non-linear, but "
5321
0
                 "TestCapability(OLCCurveGeometries) returns FALSE.");
5322
0
    }
5323
0
#endif
5324
5325
0
    return poLayer;
5326
0
}
5327
5328
//! @cond Doxygen_Suppress
5329
5330
// Technical override to avoid ambiguous choice between the old and new
5331
// new CreateLayer() signatures.
5332
OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5333
0
{
5334
0
    OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5335
0
    return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5336
0
}
5337
5338
// Technical override to avoid ambiguous choice between the old and new
5339
// new CreateLayer() signatures.
5340
OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5341
0
{
5342
0
    OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5343
0
    return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5344
0
}
5345
5346
//!@endcond
5347
5348
/************************************************************************/
5349
/*                         GDALDatasetCreateLayer()                     */
5350
/************************************************************************/
5351
5352
/**
5353
\brief This function attempts to create a new layer on the dataset with the
5354
indicated name, coordinate system, geometry type.
5355
5356
The papszOptions argument can be used to control driver specific creation
5357
options.  These options are normally documented in the format specific
5358
documentation.
5359
5360
This method is the same as the C++ method GDALDataset::CreateLayer().
5361
5362
Example:
5363
5364
\code{.c}
5365
#include "gdal.h"
5366
#include "cpl_string.h"
5367
5368
...
5369
5370
        OGRLayerH  hLayer;
5371
        char     **papszOptions;
5372
5373
        if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5374
        {
5375
        ...
5376
        }
5377
5378
        papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5379
        hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5380
                                         papszOptions );
5381
        CSLDestroy( papszOptions );
5382
5383
        if( hLayer == NULL )
5384
        {
5385
            ...
5386
        }
5387
\endcode
5388
5389
@since GDAL 2.0
5390
5391
@param hDS the dataset handle
5392
@param pszName the name for the new layer.  This should ideally not
5393
match any existing layer on the datasource.
5394
@param hSpatialRef the coordinate system to use for the new layer, or NULL if
5395
no coordinate system is available.
5396
@param eGType the geometry type for the layer.  Use wkbUnknown if there
5397
are no constraints on the types geometry to be written.
5398
@param papszOptions a StringList of name=value options.  Options are driver
5399
specific.
5400
5401
@return NULL is returned on failure, or a new OGRLayer handle on success.
5402
5403
*/
5404
5405
OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5406
                                 OGRSpatialReferenceH hSpatialRef,
5407
                                 OGRwkbGeometryType eGType,
5408
                                 CSLConstList papszOptions)
5409
5410
0
{
5411
0
    VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5412
5413
0
    if (pszName == nullptr)
5414
0
    {
5415
0
        CPLError(CE_Failure, CPLE_ObjectNull,
5416
0
                 "Name was NULL in GDALDatasetCreateLayer");
5417
0
        return nullptr;
5418
0
    }
5419
5420
0
    OGRLayerH hLayer =
5421
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5422
0
            pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5423
0
            const_cast<char **>(papszOptions)));
5424
5425
0
#ifdef OGRAPISPY_ENABLED
5426
0
    if (bOGRAPISpyEnabled)
5427
0
        OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5428
0
                                 const_cast<char **>(papszOptions), hLayer);
5429
0
#endif
5430
5431
0
    return hLayer;
5432
0
}
5433
5434
/************************************************************************/
5435
/*                 GDALDatasetCreateLayerFromGeomFieldDefn()            */
5436
/************************************************************************/
5437
5438
/**
5439
\brief This function attempts to create a new layer on the dataset with the
5440
indicated name and geometry field.
5441
5442
When poGeomFieldDefn is not null, most drivers should honor
5443
poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5444
Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5445
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5446
poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5447
very few currently.
5448
5449
Note that even if a geometry coordinate precision is set and a driver honors the
5450
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5451
OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5452
with the coordinate precision. That is they are assumed to be valid once their
5453
coordinates are rounded to it. If it might not be the case, the user may set
5454
the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5455
or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5456
the passed geometries.
5457
5458
The papszOptions argument can be used to control driver specific creation
5459
options.  These options are normally documented in the format specific
5460
documentation.
5461
5462
This method is the same as the C++ method GDALDataset::CreateLayer().
5463
5464
@param hDS the dataset handle
5465
@param pszName the name for the new layer.  This should ideally not
5466
match any existing layer on the datasource.
5467
@param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5468
a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5469
for drivers supporting that interface).
5470
@param papszOptions a StringList of name=value options.  Options are driver
5471
specific.
5472
5473
@return NULL is returned on failure, or a new OGRLayer handle on success.
5474
5475
@since GDAL 3.9
5476
5477
*/
5478
5479
OGRLayerH
5480
GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5481
                                        OGRGeomFieldDefnH hGeomFieldDefn,
5482
                                        CSLConstList papszOptions)
5483
5484
0
{
5485
0
    VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5486
5487
0
    if (!pszName)
5488
0
    {
5489
0
        CPLError(CE_Failure, CPLE_ObjectNull,
5490
0
                 "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5491
0
        return nullptr;
5492
0
    }
5493
5494
0
    OGRLayerH hLayer =
5495
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5496
0
            pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5497
0
            papszOptions));
5498
0
    return hLayer;
5499
0
}
5500
5501
/************************************************************************/
5502
/*                         GDALDatasetCopyLayer()                       */
5503
/************************************************************************/
5504
5505
/**
5506
 \brief Duplicate an existing layer.
5507
5508
 This function creates a new layer, duplicate the field definitions of the
5509
 source layer and then duplicate each features of the source layer.
5510
 The papszOptions argument
5511
 can be used to control driver specific creation options.  These options are
5512
 normally documented in the format specific documentation.
5513
 The source layer may come from another dataset.
5514
5515
 This method is the same as the C++ method GDALDataset::CopyLayer()
5516
5517
 @since GDAL 2.0
5518
5519
 @param hDS the dataset handle.
5520
 @param hSrcLayer source layer.
5521
 @param pszNewName the name of the layer to create.
5522
 @param papszOptions a StringList of name=value options.  Options are driver
5523
                     specific.
5524
5525
 @return a handle to the layer, or NULL if an error occurs.
5526
*/
5527
OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5528
                               const char *pszNewName,
5529
                               CSLConstList papszOptions)
5530
5531
0
{
5532
0
    VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5533
0
    VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5534
0
    VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5535
5536
0
    return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5537
0
        OGRLayer::FromHandle(hSrcLayer), pszNewName,
5538
0
        const_cast<char **>(papszOptions)));
5539
0
}
5540
5541
/************************************************************************/
5542
/*                        GDALDatasetExecuteSQL()                       */
5543
/************************************************************************/
5544
5545
/**
5546
 \brief Execute an SQL statement against the data store.
5547
5548
 The result of an SQL query is either NULL for statements that are in error,
5549
 or that have no results set, or an OGRLayer pointer representing a results
5550
 set from the query.  Note that this OGRLayer is in addition to the layers
5551
 in the data store and must be destroyed with
5552
 ReleaseResultSet() before the dataset is closed
5553
 (destroyed).
5554
5555
 This method is the same as the C++ method GDALDataset::ExecuteSQL()
5556
5557
 For more information on the SQL dialect supported internally by OGR
5558
 review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5559
 document.  Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5560
 to the underlying RDBMS.
5561
5562
 Starting with OGR 1.10, the <a
5563
 href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5564
 also be used.
5565
5566
 @since GDAL 2.0
5567
5568
 @param hDS the dataset handle.
5569
 @param pszStatement the SQL statement to execute.
5570
 @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5571
5572
 @param pszDialect allows control of the statement dialect. If set to NULL, the
5573
 OGR SQL engine will be used, except for RDBMS drivers that will use their
5574
 dedicated SQL engine, unless OGRSQL is explicitly passed as the
5575
 dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5576
5577
 @return an OGRLayer containing the results of the query.  Deallocate with
5578
 GDALDatasetReleaseResultSet().
5579
5580
*/
5581
5582
OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5583
                                OGRGeometryH hSpatialFilter,
5584
                                const char *pszDialect)
5585
5586
0
{
5587
0
    VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5588
5589
0
    OGRLayerH hLayer =
5590
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5591
0
            pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5592
5593
0
#ifdef OGRAPISPY_ENABLED
5594
0
    if (bOGRAPISpyEnabled)
5595
0
        OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5596
0
                                hLayer);
5597
0
#endif
5598
5599
0
    return hLayer;
5600
0
}
5601
5602
/************************************************************************/
5603
/*                        GDALDatasetAbortSQL()                         */
5604
/************************************************************************/
5605
5606
/**
5607
 \brief Abort any SQL statement running in the data store.
5608
5609
 This function can be safely called from any thread (pending that the dataset
5610
 object is still alive). Driver implementations will make sure that it can be
5611
 called in a thread-safe way.
5612
5613
 This might not be implemented by all drivers. At time of writing, only SQLite,
5614
 GPKG and PG drivers implement it
5615
5616
 This method is the same as the C++ method GDALDataset::AbortSQL()
5617
5618
 @since GDAL 3.2.0
5619
5620
 @param hDS the dataset handle.
5621
5622
 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5623
 is not supported for this datasource. .
5624
5625
*/
5626
5627
OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5628
5629
0
{
5630
0
    VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5631
0
    return GDALDataset::FromHandle(hDS)->AbortSQL();
5632
0
}
5633
5634
/************************************************************************/
5635
/*                      GDALDatasetGetStyleTable()                      */
5636
/************************************************************************/
5637
5638
/**
5639
 \brief Returns dataset style table.
5640
5641
 This function is the same as the C++ method GDALDataset::GetStyleTable()
5642
5643
 @since GDAL 2.0
5644
5645
 @param hDS the dataset handle
5646
 @return handle to a style table which should not be modified or freed by the
5647
 caller.
5648
*/
5649
5650
OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5651
5652
0
{
5653
0
    VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5654
5655
0
    return reinterpret_cast<OGRStyleTableH>(
5656
0
        GDALDataset::FromHandle(hDS)->GetStyleTable());
5657
0
}
5658
5659
/************************************************************************/
5660
/*                    GDALDatasetSetStyleTableDirectly()                */
5661
/************************************************************************/
5662
5663
/**
5664
 \brief Set dataset style table.
5665
5666
 This function operate exactly as GDALDatasetSetStyleTable() except that it
5667
 assumes ownership of the passed table.
5668
5669
 This function is the same as the C++ method
5670
 GDALDataset::SetStyleTableDirectly()
5671
5672
 @since GDAL 2.0
5673
5674
 @param hDS the dataset handle
5675
 @param hStyleTable style table handle to set
5676
5677
*/
5678
5679
void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5680
                                      OGRStyleTableH hStyleTable)
5681
5682
0
{
5683
0
    VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5684
5685
0
    GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5686
0
        reinterpret_cast<OGRStyleTable *>(hStyleTable));
5687
0
}
5688
5689
/************************************************************************/
5690
/*                     GDALDatasetSetStyleTable()                       */
5691
/************************************************************************/
5692
5693
/**
5694
 \brief Set dataset style table.
5695
5696
 This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5697
 it assumes ownership of the passed table.
5698
5699
 This function is the same as the C++ method GDALDataset::SetStyleTable()
5700
5701
 @since GDAL 2.0
5702
5703
 @param hDS the dataset handle
5704
 @param hStyleTable style table handle to set
5705
5706
*/
5707
5708
void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5709
5710
0
{
5711
0
    VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5712
0
    VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5713
5714
0
    GDALDataset::FromHandle(hDS)->SetStyleTable(
5715
0
        reinterpret_cast<OGRStyleTable *>(hStyleTable));
5716
0
}
5717
5718
/************************************************************************/
5719
/*                    ValidateLayerCreationOptions()                    */
5720
/************************************************************************/
5721
5722
//! @cond Doxygen_Suppress
5723
int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5724
0
{
5725
0
    const char *pszOptionList =
5726
0
        GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5727
0
    if (pszOptionList == nullptr && poDriver != nullptr)
5728
0
    {
5729
0
        pszOptionList =
5730
0
            poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5731
0
    }
5732
0
    CPLString osDataset;
5733
0
    osDataset.Printf("dataset %s", GetDescription());
5734
0
    return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5735
0
                               osDataset);
5736
0
}
5737
5738
//! @endcond
5739
5740
/************************************************************************/
5741
/*                              Release()                               */
5742
/************************************************************************/
5743
5744
/**
5745
\brief Drop a reference to this dataset, and if the reference count drops to one
5746
close (destroy) the dataset.
5747
5748
This method is the same as the C function OGRReleaseDataSource().
5749
5750
@deprecated. In GDAL 2, use GDALClose() instead
5751
5752
@return OGRERR_NONE on success or an error code.
5753
*/
5754
5755
OGRErr GDALDataset::Release()
5756
5757
0
{
5758
0
    ReleaseRef();
5759
0
    return OGRERR_NONE;
5760
0
}
5761
5762
/************************************************************************/
5763
/*                            GetRefCount()                             */
5764
/************************************************************************/
5765
5766
/**
5767
\brief Fetch reference count.
5768
5769
This method is the same as the C function OGR_DS_GetRefCount().
5770
5771
In GDAL 1.X, this method used to be in the OGRDataSource class.
5772
5773
@return the current reference count for the datasource object itself.
5774
*/
5775
5776
int GDALDataset::GetRefCount() const
5777
0
{
5778
0
    return nRefCount;
5779
0
}
5780
5781
/************************************************************************/
5782
/*                         GetSummaryRefCount()                         */
5783
/************************************************************************/
5784
5785
/**
5786
\brief Fetch reference count of datasource and all owned layers.
5787
5788
This method is the same as the C function  OGR_DS_GetSummaryRefCount().
5789
5790
In GDAL 1.X, this method used to be in the OGRDataSource class.
5791
5792
@deprecated
5793
5794
@return the current summary reference count for the datasource and its layers.
5795
*/
5796
5797
int GDALDataset::GetSummaryRefCount() const
5798
5799
0
{
5800
0
    CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5801
0
    int nSummaryCount = nRefCount;
5802
0
    GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5803
5804
0
    for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5805
0
        nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5806
5807
0
    return nSummaryCount;
5808
0
}
5809
5810
/************************************************************************/
5811
/*                           ICreateLayer()                             */
5812
/************************************************************************/
5813
5814
/**
5815
 \brief This method attempts to create a new layer on the dataset with the
5816
 indicated name, coordinate system, geometry type.
5817
5818
 This method is reserved to implementation by drivers.
5819
5820
 The papszOptions argument can be used to control driver specific creation
5821
 options.  These options are normally documented in the format specific
5822
 documentation.
5823
5824
 @param pszName the name for the new layer.  This should ideally not
5825
 match any existing layer on the datasource.
5826
 @param poGeomFieldDefn the geometry field definition to use for the new layer,
5827
 or NULL if there is no geometry field.
5828
 @param papszOptions a StringList of name=value options.  Options are driver
5829
 specific.
5830
5831
 @return NULL is returned on failure, or a new OGRLayer handle on success.
5832
5833
 @since GDAL 2.0 (prototype modified in 3.9)
5834
*/
5835
5836
OGRLayer *
5837
GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5838
                          CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5839
                          CPL_UNUSED CSLConstList papszOptions)
5840
5841
0
{
5842
0
    CPLError(CE_Failure, CPLE_NotSupported,
5843
0
             "CreateLayer() not supported by this dataset.");
5844
5845
0
    return nullptr;
5846
0
}
5847
5848
/************************************************************************/
5849
/*                             CopyLayer()                              */
5850
/************************************************************************/
5851
5852
/**
5853
 \brief Duplicate an existing layer.
5854
5855
 This method creates a new layer, duplicate the field definitions of the
5856
 source layer and then duplicate each features of the source layer.
5857
 The papszOptions argument
5858
 can be used to control driver specific creation options.  These options are
5859
 normally documented in the format specific documentation.
5860
 The source layer may come from another dataset.
5861
5862
 This method is the same as the C function GDALDatasetCopyLayer() and the
5863
 deprecated OGR_DS_CopyLayer().
5864
5865
 In GDAL 1.X, this method used to be in the OGRDataSource class.
5866
5867
 @param poSrcLayer source layer.
5868
 @param pszNewName the name of the layer to create.
5869
 @param papszOptions a StringList of name=value options.  Options are driver
5870
                     specific. There is a common option to set output layer
5871
                     spatial reference: DST_SRSWKT. The option should be in
5872
                     WKT format. Starting with GDAL 3.7, the common option
5873
                     COPY_MD can be set to NO to prevent the default copying
5874
                     of the metadata from the source layer to the target layer.
5875
5876
 @return a handle to the layer, or NULL if an error occurs.
5877
*/
5878
5879
OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
5880
                                 char **papszOptions)
5881
5882
0
{
5883
    /* -------------------------------------------------------------------- */
5884
    /*      Create the layer.                                               */
5885
    /* -------------------------------------------------------------------- */
5886
0
    if (!TestCapability(ODsCCreateLayer))
5887
0
    {
5888
0
        CPLError(CE_Failure, CPLE_NotSupported,
5889
0
                 "This datasource does not support creation of layers.");
5890
0
        return nullptr;
5891
0
    }
5892
5893
0
    const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5894
0
    OGRSpatialReference oDstSpaRef(pszSRSWKT);
5895
0
    oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5896
0
    OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5897
0
    OGRLayer *poDstLayer = nullptr;
5898
5899
0
    CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
5900
0
    aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
5901
0
    aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
5902
5903
0
    CPLErrorReset();
5904
0
    const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5905
0
    if (nSrcGeomFieldCount == 1)
5906
0
    {
5907
0
        OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
5908
0
        if (pszSRSWKT)
5909
0
            oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
5910
0
        poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
5911
0
                                  aosCleanedUpOptions.List());
5912
0
    }
5913
0
    else
5914
0
    {
5915
0
        poDstLayer =
5916
0
            ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
5917
0
    }
5918
5919
0
    if (poDstLayer == nullptr)
5920
0
        return nullptr;
5921
5922
0
    if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
5923
0
    {
5924
0
        char **papszMD = poSrcLayer->GetMetadata();
5925
0
        if (papszMD)
5926
0
            poDstLayer->SetMetadata(papszMD);
5927
0
    }
5928
5929
    /* -------------------------------------------------------------------- */
5930
    /*      Add fields.  Default to copy all fields, and make sure to       */
5931
    /*      establish a mapping between indices, rather than names, in      */
5932
    /*      case the target datasource has altered it (e.g. Shapefile       */
5933
    /*      limited to 10 char field names).                                */
5934
    /* -------------------------------------------------------------------- */
5935
0
    const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5936
5937
    // Initialize the index-to-index map to -1's.
5938
0
    std::vector<int> anMap(nSrcFieldCount, -1);
5939
5940
    // Caution: At the time of writing, the MapInfo driver
5941
    // returns NULL until a field has been added.
5942
0
    OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5943
0
    int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5944
0
    for (int iField = 0; iField < nSrcFieldCount; ++iField)
5945
0
    {
5946
0
        OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5947
0
        OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5948
5949
        // The field may have been already created at layer creation.
5950
0
        int iDstField = -1;
5951
0
        if (poDstFDefn)
5952
0
            iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5953
0
        if (iDstField >= 0)
5954
0
        {
5955
0
            anMap[iField] = iDstField;
5956
0
        }
5957
0
        else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
5958
0
        {
5959
            // Now that we've created a field, GetLayerDefn() won't return NULL.
5960
0
            if (poDstFDefn == nullptr)
5961
0
                poDstFDefn = poDstLayer->GetLayerDefn();
5962
5963
            // Sanity check: if it fails, the driver is buggy.
5964
0
            if (poDstFDefn != nullptr &&
5965
0
                poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5966
0
            {
5967
0
                CPLError(CE_Warning, CPLE_AppDefined,
5968
0
                         "The output driver has claimed to have added the %s "
5969
0
                         "field, but it did not!",
5970
0
                         oFieldDefn.GetNameRef());
5971
0
            }
5972
0
            else
5973
0
            {
5974
0
                anMap[iField] = nDstFieldCount;
5975
0
                ++nDstFieldCount;
5976
0
            }
5977
0
        }
5978
0
    }
5979
5980
    /* -------------------------------------------------------------------- */
5981
0
    std::unique_ptr<OGRCoordinateTransformation> poCT;
5982
0
    OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5983
0
    if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
5984
0
        sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5985
0
    {
5986
0
        poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
5987
0
        if (nullptr == poCT)
5988
0
        {
5989
0
            CPLError(CE_Failure, CPLE_NotSupported,
5990
0
                     "This input/output spatial reference is not supported.");
5991
0
            return nullptr;
5992
0
        }
5993
0
    }
5994
    /* -------------------------------------------------------------------- */
5995
    /*      Create geometry fields.                                         */
5996
    /* -------------------------------------------------------------------- */
5997
0
    if (nSrcGeomFieldCount > 1 &&
5998
0
        TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
5999
0
    {
6000
6001
0
        for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6002
0
        {
6003
0
            if (nullptr == pszSRSWKT)
6004
0
            {
6005
0
                poDstLayer->CreateGeomField(
6006
0
                    poSrcDefn->GetGeomFieldDefn(iField));
6007
0
            }
6008
0
            else
6009
0
            {
6010
0
                OGRGeomFieldDefn *pDstGeomFieldDefn =
6011
0
                    poSrcDefn->GetGeomFieldDefn(iField);
6012
0
                pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
6013
0
                poDstLayer->CreateGeomField(pDstGeomFieldDefn);
6014
0
            }
6015
0
        }
6016
0
    }
6017
6018
    /* -------------------------------------------------------------------- */
6019
    /*      Check if the destination layer supports transactions and set a  */
6020
    /*      default number of features in a single transaction.             */
6021
    /* -------------------------------------------------------------------- */
6022
0
    const int nGroupTransactions =
6023
0
        poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
6024
6025
    /* -------------------------------------------------------------------- */
6026
    /*      Transfer features.                                              */
6027
    /* -------------------------------------------------------------------- */
6028
0
    poSrcLayer->ResetReading();
6029
6030
0
    if (nGroupTransactions <= 0)
6031
0
    {
6032
0
        while (true)
6033
0
        {
6034
0
            auto poFeature =
6035
0
                std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
6036
6037
0
            if (poFeature == nullptr)
6038
0
                break;
6039
6040
0
            CPLErrorReset();
6041
0
            auto poDstFeature =
6042
0
                std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
6043
6044
0
            if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
6045
0
                OGRERR_NONE)
6046
0
            {
6047
0
                CPLError(CE_Failure, CPLE_AppDefined,
6048
0
                         "Unable to translate feature " CPL_FRMT_GIB
6049
0
                         " from layer %s.",
6050
0
                         poFeature->GetFID(), poSrcDefn->GetName());
6051
0
                return poDstLayer;
6052
0
            }
6053
6054
0
            if (nullptr != poCT)
6055
0
            {
6056
0
                for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6057
0
                {
6058
0
                    OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
6059
0
                    if (nullptr == pGeom)
6060
0
                        continue;
6061
6062
0
                    const OGRErr eErr = pGeom->transform(poCT.get());
6063
0
                    if (eErr == OGRERR_NONE)
6064
0
                        continue;
6065
6066
0
                    CPLError(CE_Failure, CPLE_AppDefined,
6067
0
                             "Unable to transform geometry " CPL_FRMT_GIB
6068
0
                             " from layer %s.",
6069
0
                             poFeature->GetFID(), poSrcDefn->GetName());
6070
0
                    return poDstLayer;
6071
0
                }
6072
0
            }
6073
6074
0
            poDstFeature->SetFID(poFeature->GetFID());
6075
6076
0
            CPLErrorReset();
6077
0
            if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
6078
0
            {
6079
0
                return poDstLayer;
6080
0
            }
6081
0
        }
6082
0
    }
6083
0
    else
6084
0
    {
6085
0
        std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
6086
0
        try
6087
0
        {
6088
0
            apoDstFeatures.resize(nGroupTransactions);
6089
0
        }
6090
0
        catch (const std::exception &e)
6091
0
        {
6092
0
            CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
6093
0
            return poDstLayer;
6094
0
        }
6095
0
        bool bStopTransfer = false;
6096
0
        while (!bStopTransfer)
6097
0
        {
6098
            /* --------------------------------------------------------------------
6099
             */
6100
            /*      Fill the array with features. */
6101
            /* --------------------------------------------------------------------
6102
             */
6103
            // Number of features in the temporary array.
6104
0
            int nFeatCount = 0;  // Used after for.
6105
0
            for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
6106
0
            {
6107
0
                auto poFeature =
6108
0
                    std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
6109
6110
0
                if (poFeature == nullptr)
6111
0
                {
6112
0
                    bStopTransfer = true;
6113
0
                    break;
6114
0
                }
6115
6116
0
                CPLErrorReset();
6117
0
                apoDstFeatures[nFeatCount] =
6118
0
                    std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
6119
6120
0
                if (apoDstFeatures[nFeatCount]->SetFrom(
6121
0
                        poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
6122
0
                {
6123
0
                    CPLError(CE_Failure, CPLE_AppDefined,
6124
0
                             "Unable to translate feature " CPL_FRMT_GIB
6125
0
                             " from layer %s.",
6126
0
                             poFeature->GetFID(), poSrcDefn->GetName());
6127
0
                    bStopTransfer = true;
6128
0
                    poFeature.reset();
6129
0
                    break;
6130
0
                }
6131
6132
0
                if (nullptr != poCT)
6133
0
                {
6134
0
                    for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
6135
0
                    {
6136
0
                        OGRGeometry *pGeom =
6137
0
                            apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
6138
0
                        if (nullptr == pGeom)
6139
0
                            continue;
6140
6141
0
                        const OGRErr eErr = pGeom->transform(poCT.get());
6142
0
                        if (eErr == OGRERR_NONE)
6143
0
                            continue;
6144
6145
0
                        CPLError(CE_Failure, CPLE_AppDefined,
6146
0
                                 "Unable to transform geometry " CPL_FRMT_GIB
6147
0
                                 " from layer %s.",
6148
0
                                 poFeature->GetFID(), poSrcDefn->GetName());
6149
0
                        bStopTransfer = true;
6150
0
                        poFeature.reset();
6151
0
                        break;
6152
0
                    }
6153
0
                }
6154
6155
0
                if (poFeature)
6156
0
                {
6157
0
                    apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
6158
0
                }
6159
0
            }
6160
6161
0
            CPLErrorReset();
6162
0
            bool bStopTransaction = false;
6163
0
            while (!bStopTransaction)
6164
0
            {
6165
0
                bStopTransaction = true;
6166
0
                if (poDstLayer->StartTransaction() != OGRERR_NONE)
6167
0
                    break;
6168
0
                for (int i = 0; i < nFeatCount; ++i)
6169
0
                {
6170
0
                    if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
6171
0
                        OGRERR_NONE)
6172
0
                    {
6173
0
                        bStopTransfer = true;
6174
0
                        bStopTransaction = false;
6175
0
                        break;
6176
0
                    }
6177
0
                    apoDstFeatures[i].reset();
6178
0
                }
6179
0
                if (bStopTransaction)
6180
0
                {
6181
0
                    if (poDstLayer->CommitTransaction() != OGRERR_NONE)
6182
0
                        break;
6183
0
                }
6184
0
                else
6185
0
                {
6186
0
                    poDstLayer->RollbackTransaction();
6187
0
                }
6188
0
            }
6189
0
        }
6190
0
    }
6191
6192
0
    return poDstLayer;
6193
0
}
6194
6195
/************************************************************************/
6196
/*                            DeleteLayer()                             */
6197
/************************************************************************/
6198
6199
/**
6200
 \fn GDALDataset::DeleteLayer(int)
6201
 \brief Delete the indicated layer from the datasource.
6202
6203
 If this method is supported
6204
 the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
6205
6206
 This method is the same as the C function GDALDatasetDeleteLayer() and the
6207
 deprecated OGR_DS_DeleteLayer().
6208
6209
 In GDAL 1.X, this method used to be in the OGRDataSource class.
6210
6211
 @param iLayer the index of the layer to delete.
6212
6213
 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
6214
 layers is not supported for this datasource.
6215
6216
*/
6217
6218
OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
6219
6220
0
{
6221
0
    CPLError(CE_Failure, CPLE_NotSupported,
6222
0
             "DeleteLayer() not supported by this dataset.");
6223
6224
0
    return OGRERR_UNSUPPORTED_OPERATION;
6225
0
}
6226
6227
/************************************************************************/
6228
/*                           GetLayerByName()                           */
6229
/************************************************************************/
6230
6231
/**
6232
 \brief Fetch a layer by name.
6233
6234
 The returned layer remains owned by the
6235
 GDALDataset and should not be deleted by the application.
6236
6237
 This method is the same as the C function GDALDatasetGetLayerByName() and the
6238
 deprecated OGR_DS_GetLayerByName().
6239
6240
 In GDAL 1.X, this method used to be in the OGRDataSource class.
6241
6242
 @param pszName the layer name of the layer to fetch.
6243
6244
 @return the layer, or NULL if Layer is not found or an error occurs.
6245
*/
6246
6247
OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6248
6249
0
{
6250
0
    CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6251
6252
0
    if (!pszName)
6253
0
        return nullptr;
6254
6255
    // First a case sensitive check.
6256
0
    for (int i = 0; i < GetLayerCount(); ++i)
6257
0
    {
6258
0
        OGRLayer *poLayer = GetLayer(i);
6259
6260
0
        if (strcmp(pszName, poLayer->GetName()) == 0)
6261
0
            return poLayer;
6262
0
    }
6263
6264
    // Then case insensitive.
6265
0
    for (int i = 0; i < GetLayerCount(); ++i)
6266
0
    {
6267
0
        OGRLayer *poLayer = GetLayer(i);
6268
6269
0
        if (EQUAL(pszName, poLayer->GetName()))
6270
0
            return poLayer;
6271
0
    }
6272
6273
0
    return nullptr;
6274
0
}
6275
6276
//! @cond Doxygen_Suppress
6277
/************************************************************************/
6278
/*                       ProcessSQLCreateIndex()                        */
6279
/*                                                                      */
6280
/*      The correct syntax for creating an index in our dialect of      */
6281
/*      SQL is:                                                         */
6282
/*                                                                      */
6283
/*        CREATE INDEX ON <layername> USING <columnname>                */
6284
/************************************************************************/
6285
6286
OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6287
6288
0
{
6289
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6290
6291
    /* -------------------------------------------------------------------- */
6292
    /*      Do some general syntax checking.                                */
6293
    /* -------------------------------------------------------------------- */
6294
0
    if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6295
0
        !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6296
0
        !EQUAL(papszTokens[4], "USING"))
6297
0
    {
6298
0
        CSLDestroy(papszTokens);
6299
0
        CPLError(CE_Failure, CPLE_AppDefined,
6300
0
                 "Syntax error in CREATE INDEX command.\n"
6301
0
                 "Was '%s'\n"
6302
0
                 "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6303
0
                 pszSQLCommand);
6304
0
        return OGRERR_FAILURE;
6305
0
    }
6306
6307
    /* -------------------------------------------------------------------- */
6308
    /*      Find the named layer.                                           */
6309
    /* -------------------------------------------------------------------- */
6310
0
    OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6311
0
    if (poLayer == nullptr)
6312
0
    {
6313
0
        CPLError(CE_Failure, CPLE_AppDefined,
6314
0
                 "CREATE INDEX ON failed, no such layer as `%s'.",
6315
0
                 papszTokens[3]);
6316
0
        CSLDestroy(papszTokens);
6317
0
        return OGRERR_FAILURE;
6318
0
    }
6319
6320
    /* -------------------------------------------------------------------- */
6321
    /*      Does this layer even support attribute indexes?                 */
6322
    /* -------------------------------------------------------------------- */
6323
0
    if (poLayer->GetIndex() == nullptr)
6324
0
    {
6325
0
        CPLError(CE_Failure, CPLE_AppDefined,
6326
0
                 "CREATE INDEX ON not supported by this driver.");
6327
0
        CSLDestroy(papszTokens);
6328
0
        return OGRERR_FAILURE;
6329
0
    }
6330
6331
    /* -------------------------------------------------------------------- */
6332
    /*      Find the named field.                                           */
6333
    /* -------------------------------------------------------------------- */
6334
0
    int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6335
6336
0
    CSLDestroy(papszTokens);
6337
6338
0
    if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6339
0
    {
6340
0
        CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6341
0
                 pszSQLCommand);
6342
0
        return OGRERR_FAILURE;
6343
0
    }
6344
6345
    /* -------------------------------------------------------------------- */
6346
    /*      Attempt to create the index.                                    */
6347
    /* -------------------------------------------------------------------- */
6348
0
    OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6349
0
    if (eErr == OGRERR_NONE)
6350
0
    {
6351
0
        eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6352
0
    }
6353
0
    else
6354
0
    {
6355
0
        if (strlen(CPLGetLastErrorMsg()) == 0)
6356
0
            CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6357
0
    }
6358
6359
0
    return eErr;
6360
0
}
6361
6362
/************************************************************************/
6363
/*                        ProcessSQLDropIndex()                         */
6364
/*                                                                      */
6365
/*      The correct syntax for dropping one or more indexes in          */
6366
/*      the OGR SQL dialect is:                                         */
6367
/*                                                                      */
6368
/*          DROP INDEX ON <layername> [USING <columnname>]              */
6369
/************************************************************************/
6370
6371
OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6372
6373
0
{
6374
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6375
6376
    /* -------------------------------------------------------------------- */
6377
    /*      Do some general syntax checking.                                */
6378
    /* -------------------------------------------------------------------- */
6379
0
    if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6380
0
        !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6381
0
        !EQUAL(papszTokens[2], "ON") ||
6382
0
        (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6383
0
    {
6384
0
        CSLDestroy(papszTokens);
6385
0
        CPLError(CE_Failure, CPLE_AppDefined,
6386
0
                 "Syntax error in DROP INDEX command.\n"
6387
0
                 "Was '%s'\n"
6388
0
                 "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6389
0
                 pszSQLCommand);
6390
0
        return OGRERR_FAILURE;
6391
0
    }
6392
6393
    /* -------------------------------------------------------------------- */
6394
    /*      Find the named layer.                                           */
6395
    /* -------------------------------------------------------------------- */
6396
0
    OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6397
0
    if (poLayer == nullptr)
6398
0
    {
6399
0
        CPLError(CE_Failure, CPLE_AppDefined,
6400
0
                 "DROP INDEX ON failed, no such layer as `%s'.",
6401
0
                 papszTokens[3]);
6402
0
        CSLDestroy(papszTokens);
6403
0
        return OGRERR_FAILURE;
6404
0
    }
6405
6406
    /* -------------------------------------------------------------------- */
6407
    /*      Does this layer even support attribute indexes?                 */
6408
    /* -------------------------------------------------------------------- */
6409
0
    if (poLayer->GetIndex() == nullptr)
6410
0
    {
6411
0
        CPLError(CE_Failure, CPLE_AppDefined,
6412
0
                 "Indexes not supported by this driver.");
6413
0
        CSLDestroy(papszTokens);
6414
0
        return OGRERR_FAILURE;
6415
0
    }
6416
6417
    /* -------------------------------------------------------------------- */
6418
    /*      If we were not given a field name, drop all indexes.            */
6419
    /* -------------------------------------------------------------------- */
6420
0
    if (CSLCount(papszTokens) == 4)
6421
0
    {
6422
0
        for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6423
0
        {
6424
0
            OGRAttrIndex *poAttrIndex;
6425
6426
0
            poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6427
0
            if (poAttrIndex != nullptr)
6428
0
            {
6429
0
                const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6430
0
                if (eErr != OGRERR_NONE)
6431
0
                {
6432
0
                    CSLDestroy(papszTokens);
6433
0
                    return eErr;
6434
0
                }
6435
0
            }
6436
0
        }
6437
6438
0
        CSLDestroy(papszTokens);
6439
0
        return OGRERR_NONE;
6440
0
    }
6441
6442
    /* -------------------------------------------------------------------- */
6443
    /*      Find the named field.                                           */
6444
    /* -------------------------------------------------------------------- */
6445
0
    int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6446
0
    CSLDestroy(papszTokens);
6447
6448
0
    if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6449
0
    {
6450
0
        CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6451
0
                 pszSQLCommand);
6452
0
        return OGRERR_FAILURE;
6453
0
    }
6454
6455
    /* -------------------------------------------------------------------- */
6456
    /*      Attempt to drop the index.                                      */
6457
    /* -------------------------------------------------------------------- */
6458
0
    const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6459
6460
0
    return eErr;
6461
0
}
6462
6463
/************************************************************************/
6464
/*                        ProcessSQLDropTable()                         */
6465
/*                                                                      */
6466
/*      The correct syntax for dropping a table (layer) in the OGR SQL  */
6467
/*      dialect is:                                                     */
6468
/*                                                                      */
6469
/*          DROP TABLE <layername>                                      */
6470
/************************************************************************/
6471
6472
OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6473
6474
0
{
6475
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6476
6477
    /* -------------------------------------------------------------------- */
6478
    /*      Do some general syntax checking.                                */
6479
    /* -------------------------------------------------------------------- */
6480
0
    if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6481
0
        !EQUAL(papszTokens[1], "TABLE"))
6482
0
    {
6483
0
        CSLDestroy(papszTokens);
6484
0
        CPLError(CE_Failure, CPLE_AppDefined,
6485
0
                 "Syntax error in DROP TABLE command.\n"
6486
0
                 "Was '%s'\n"
6487
0
                 "Should be of form 'DROP TABLE <table>'",
6488
0
                 pszSQLCommand);
6489
0
        return OGRERR_FAILURE;
6490
0
    }
6491
6492
    /* -------------------------------------------------------------------- */
6493
    /*      Find the named layer.                                           */
6494
    /* -------------------------------------------------------------------- */
6495
0
    OGRLayer *poLayer = nullptr;
6496
6497
0
    int i = 0;  // Used after for.
6498
0
    for (; i < GetLayerCount(); ++i)
6499
0
    {
6500
0
        poLayer = GetLayer(i);
6501
6502
0
        if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6503
0
            break;
6504
0
        poLayer = nullptr;
6505
0
    }
6506
6507
0
    if (poLayer == nullptr)
6508
0
    {
6509
0
        CPLError(CE_Failure, CPLE_AppDefined,
6510
0
                 "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6511
0
        CSLDestroy(papszTokens);
6512
0
        return OGRERR_FAILURE;
6513
0
    }
6514
6515
0
    CSLDestroy(papszTokens);
6516
6517
    /* -------------------------------------------------------------------- */
6518
    /*      Delete it.                                                      */
6519
    /* -------------------------------------------------------------------- */
6520
6521
0
    return DeleteLayer(i);
6522
0
}
6523
6524
//! @endcond
6525
6526
/************************************************************************/
6527
/*                    GDALDatasetParseSQLType()                       */
6528
/************************************************************************/
6529
6530
/* All arguments will be altered */
6531
static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6532
                                            int &nPrecision)
6533
0
{
6534
0
    char *pszParenthesis = strchr(pszType, '(');
6535
0
    if (pszParenthesis)
6536
0
    {
6537
0
        nWidth = atoi(pszParenthesis + 1);
6538
0
        *pszParenthesis = '\0';
6539
0
        char *pszComma = strchr(pszParenthesis + 1, ',');
6540
0
        if (pszComma)
6541
0
            nPrecision = atoi(pszComma + 1);
6542
0
    }
6543
6544
0
    OGRFieldType eType = OFTString;
6545
0
    if (EQUAL(pszType, "INTEGER"))
6546
0
        eType = OFTInteger;
6547
0
    else if (EQUAL(pszType, "INTEGER[]"))
6548
0
        eType = OFTIntegerList;
6549
0
    else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6550
0
             EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6551
0
             EQUAL(pszType, "REAL") /* unofficial alias */)
6552
0
        eType = OFTReal;
6553
0
    else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6554
0
             EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6555
0
             EQUAL(pszType, "REAL[]") /* unofficial alias */)
6556
0
        eType = OFTRealList;
6557
0
    else if (EQUAL(pszType, "CHARACTER") ||
6558
0
             EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6559
0
             EQUAL(pszType, "STRING") /* unofficial alias */ ||
6560
0
             EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6561
0
        eType = OFTString;
6562
0
    else if (EQUAL(pszType, "TEXT[]") ||
6563
0
             EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6564
0
             EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6565
0
        eType = OFTStringList;
6566
0
    else if (EQUAL(pszType, "DATE"))
6567
0
        eType = OFTDate;
6568
0
    else if (EQUAL(pszType, "TIME"))
6569
0
        eType = OFTTime;
6570
0
    else if (EQUAL(pszType, "TIMESTAMP") ||
6571
0
             EQUAL(pszType, "DATETIME") /* unofficial alias */)
6572
0
        eType = OFTDateTime;
6573
0
    else
6574
0
        CPLError(CE_Warning, CPLE_NotSupported,
6575
0
                 "Unsupported column type '%s'. Defaulting to VARCHAR",
6576
0
                 pszType);
6577
6578
0
    return eType;
6579
0
}
6580
6581
/************************************************************************/
6582
/*                    ProcessSQLAlterTableAddColumn()                   */
6583
/*                                                                      */
6584
/*      The correct syntax for adding a column in the OGR SQL           */
6585
/*      dialect is:                                                     */
6586
/*                                                                      */
6587
/*       ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6588
/************************************************************************/
6589
6590
//! @cond Doxygen_Suppress
6591
OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6592
6593
0
{
6594
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6595
6596
    /* -------------------------------------------------------------------- */
6597
    /*      Do some general syntax checking.                                */
6598
    /* -------------------------------------------------------------------- */
6599
0
    const char *pszLayerName = nullptr;
6600
0
    const char *pszColumnName = nullptr;
6601
0
    int iTypeIndex = 0;
6602
0
    const int nTokens = CSLCount(papszTokens);
6603
6604
0
    if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6605
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6606
0
        EQUAL(papszTokens[4], "COLUMN"))
6607
0
    {
6608
0
        pszLayerName = papszTokens[2];
6609
0
        pszColumnName = papszTokens[5];
6610
0
        iTypeIndex = 6;
6611
0
    }
6612
0
    else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6613
0
             EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6614
0
    {
6615
0
        pszLayerName = papszTokens[2];
6616
0
        pszColumnName = papszTokens[4];
6617
0
        iTypeIndex = 5;
6618
0
    }
6619
0
    else
6620
0
    {
6621
0
        CSLDestroy(papszTokens);
6622
0
        CPLError(CE_Failure, CPLE_AppDefined,
6623
0
                 "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6624
0
                 "Was '%s'\n"
6625
0
                 "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6626
0
                 "<columnname> <columntype>'",
6627
0
                 pszSQLCommand);
6628
0
        return OGRERR_FAILURE;
6629
0
    }
6630
6631
    /* -------------------------------------------------------------------- */
6632
    /*      Merge type components into a single string if there were split  */
6633
    /*      with spaces                                                     */
6634
    /* -------------------------------------------------------------------- */
6635
0
    CPLString osType;
6636
0
    for (int i = iTypeIndex; i < nTokens; ++i)
6637
0
    {
6638
0
        osType += papszTokens[i];
6639
0
        CPLFree(papszTokens[i]);
6640
0
    }
6641
0
    char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6642
0
    papszTokens[iTypeIndex + 1] = nullptr;
6643
6644
    /* -------------------------------------------------------------------- */
6645
    /*      Find the named layer.                                           */
6646
    /* -------------------------------------------------------------------- */
6647
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6648
0
    if (poLayer == nullptr)
6649
0
    {
6650
0
        CPLError(CE_Failure, CPLE_AppDefined,
6651
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6652
0
                 pszLayerName);
6653
0
        CSLDestroy(papszTokens);
6654
0
        return OGRERR_FAILURE;
6655
0
    }
6656
6657
    /* -------------------------------------------------------------------- */
6658
    /*      Add column.                                                     */
6659
    /* -------------------------------------------------------------------- */
6660
6661
0
    int nWidth = 0;
6662
0
    int nPrecision = 0;
6663
0
    OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6664
0
    OGRFieldDefn oFieldDefn(pszColumnName, eType);
6665
0
    oFieldDefn.SetWidth(nWidth);
6666
0
    oFieldDefn.SetPrecision(nPrecision);
6667
6668
0
    CSLDestroy(papszTokens);
6669
6670
0
    return poLayer->CreateField(&oFieldDefn);
6671
0
}
6672
6673
/************************************************************************/
6674
/*                    ProcessSQLAlterTableDropColumn()                  */
6675
/*                                                                      */
6676
/*      The correct syntax for dropping a column in the OGR SQL         */
6677
/*      dialect is:                                                     */
6678
/*                                                                      */
6679
/*          ALTER TABLE <layername> DROP [COLUMN] <columnname>          */
6680
/************************************************************************/
6681
6682
OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6683
6684
0
{
6685
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6686
6687
    /* -------------------------------------------------------------------- */
6688
    /*      Do some general syntax checking.                                */
6689
    /* -------------------------------------------------------------------- */
6690
0
    const char *pszLayerName = nullptr;
6691
0
    const char *pszColumnName = nullptr;
6692
0
    if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6693
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6694
0
        EQUAL(papszTokens[4], "COLUMN"))
6695
0
    {
6696
0
        pszLayerName = papszTokens[2];
6697
0
        pszColumnName = papszTokens[5];
6698
0
    }
6699
0
    else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6700
0
             EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6701
0
    {
6702
0
        pszLayerName = papszTokens[2];
6703
0
        pszColumnName = papszTokens[4];
6704
0
    }
6705
0
    else
6706
0
    {
6707
0
        CSLDestroy(papszTokens);
6708
0
        CPLError(CE_Failure, CPLE_AppDefined,
6709
0
                 "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6710
0
                 "Was '%s'\n"
6711
0
                 "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6712
0
                 "<columnname>'",
6713
0
                 pszSQLCommand);
6714
0
        return OGRERR_FAILURE;
6715
0
    }
6716
6717
    /* -------------------------------------------------------------------- */
6718
    /*      Find the named layer.                                           */
6719
    /* -------------------------------------------------------------------- */
6720
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6721
0
    if (poLayer == nullptr)
6722
0
    {
6723
0
        CPLError(CE_Failure, CPLE_AppDefined,
6724
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6725
0
                 pszLayerName);
6726
0
        CSLDestroy(papszTokens);
6727
0
        return OGRERR_FAILURE;
6728
0
    }
6729
6730
    /* -------------------------------------------------------------------- */
6731
    /*      Find the field.                                                 */
6732
    /* -------------------------------------------------------------------- */
6733
6734
0
    int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6735
0
    if (nFieldIndex < 0)
6736
0
    {
6737
0
        CPLError(CE_Failure, CPLE_AppDefined,
6738
0
                 "%s failed, no such field as `%s'.", pszSQLCommand,
6739
0
                 pszColumnName);
6740
0
        CSLDestroy(papszTokens);
6741
0
        return OGRERR_FAILURE;
6742
0
    }
6743
6744
    /* -------------------------------------------------------------------- */
6745
    /*      Remove it.                                                      */
6746
    /* -------------------------------------------------------------------- */
6747
6748
0
    CSLDestroy(papszTokens);
6749
6750
0
    return poLayer->DeleteField(nFieldIndex);
6751
0
}
6752
6753
/************************************************************************/
6754
/*                 ProcessSQLAlterTableRenameColumn()                   */
6755
/*                                                                      */
6756
/*      The correct syntax for renaming a column in the OGR SQL         */
6757
/*      dialect is:                                                     */
6758
/*                                                                      */
6759
/*       ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6760
/************************************************************************/
6761
6762
OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6763
6764
0
{
6765
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6766
6767
    /* -------------------------------------------------------------------- */
6768
    /*      Do some general syntax checking.                                */
6769
    /* -------------------------------------------------------------------- */
6770
0
    const char *pszLayerName = nullptr;
6771
0
    const char *pszOldColName = nullptr;
6772
0
    const char *pszNewColName = nullptr;
6773
0
    if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6774
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6775
0
        EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6776
0
    {
6777
0
        pszLayerName = papszTokens[2];
6778
0
        pszOldColName = papszTokens[5];
6779
0
        pszNewColName = papszTokens[7];
6780
0
    }
6781
0
    else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6782
0
             EQUAL(papszTokens[1], "TABLE") &&
6783
0
             EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6784
0
    {
6785
0
        pszLayerName = papszTokens[2];
6786
0
        pszOldColName = papszTokens[4];
6787
0
        pszNewColName = papszTokens[6];
6788
0
    }
6789
0
    else
6790
0
    {
6791
0
        CSLDestroy(papszTokens);
6792
0
        CPLError(CE_Failure, CPLE_AppDefined,
6793
0
                 "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6794
0
                 "Was '%s'\n"
6795
0
                 "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6796
0
                 "<columnname> TO <newname>'",
6797
0
                 pszSQLCommand);
6798
0
        return OGRERR_FAILURE;
6799
0
    }
6800
6801
    /* -------------------------------------------------------------------- */
6802
    /*      Find the named layer.                                           */
6803
    /* -------------------------------------------------------------------- */
6804
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6805
0
    if (poLayer == nullptr)
6806
0
    {
6807
0
        CPLError(CE_Failure, CPLE_AppDefined,
6808
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6809
0
                 pszLayerName);
6810
0
        CSLDestroy(papszTokens);
6811
0
        return OGRERR_FAILURE;
6812
0
    }
6813
6814
    /* -------------------------------------------------------------------- */
6815
    /*      Find the field.                                                 */
6816
    /* -------------------------------------------------------------------- */
6817
6818
0
    const int nFieldIndex =
6819
0
        poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6820
0
    if (nFieldIndex < 0)
6821
0
    {
6822
0
        CPLError(CE_Failure, CPLE_AppDefined,
6823
0
                 "%s failed, no such field as `%s'.", pszSQLCommand,
6824
0
                 pszOldColName);
6825
0
        CSLDestroy(papszTokens);
6826
0
        return OGRERR_FAILURE;
6827
0
    }
6828
6829
    /* -------------------------------------------------------------------- */
6830
    /*      Rename column.                                                  */
6831
    /* -------------------------------------------------------------------- */
6832
0
    OGRFieldDefn *poOldFieldDefn =
6833
0
        poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6834
0
    OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6835
0
    oNewFieldDefn.SetName(pszNewColName);
6836
6837
0
    CSLDestroy(papszTokens);
6838
6839
0
    return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6840
0
                                   ALTER_NAME_FLAG);
6841
0
}
6842
6843
/************************************************************************/
6844
/*                 ProcessSQLAlterTableAlterColumn()                    */
6845
/*                                                                      */
6846
/*      The correct syntax for altering the type of a column in the     */
6847
/*      OGR SQL dialect is:                                             */
6848
/*                                                                      */
6849
/*   ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6850
/************************************************************************/
6851
6852
OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
6853
6854
0
{
6855
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6856
6857
    /* -------------------------------------------------------------------- */
6858
    /*      Do some general syntax checking.                                */
6859
    /* -------------------------------------------------------------------- */
6860
0
    const char *pszLayerName = nullptr;
6861
0
    const char *pszColumnName = nullptr;
6862
0
    int iTypeIndex = 0;
6863
0
    const int nTokens = CSLCount(papszTokens);
6864
6865
0
    if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
6866
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6867
0
        EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
6868
0
    {
6869
0
        pszLayerName = papszTokens[2];
6870
0
        pszColumnName = papszTokens[5];
6871
0
        iTypeIndex = 7;
6872
0
    }
6873
0
    else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6874
0
             EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6875
0
             EQUAL(papszTokens[5], "TYPE"))
6876
0
    {
6877
0
        pszLayerName = papszTokens[2];
6878
0
        pszColumnName = papszTokens[4];
6879
0
        iTypeIndex = 6;
6880
0
    }
6881
0
    else
6882
0
    {
6883
0
        CSLDestroy(papszTokens);
6884
0
        CPLError(CE_Failure, CPLE_AppDefined,
6885
0
                 "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6886
0
                 "Was '%s'\n"
6887
0
                 "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6888
0
                 "<columnname> TYPE <columntype>'",
6889
0
                 pszSQLCommand);
6890
0
        return OGRERR_FAILURE;
6891
0
    }
6892
6893
    /* -------------------------------------------------------------------- */
6894
    /*      Merge type components into a single string if there were split  */
6895
    /*      with spaces                                                     */
6896
    /* -------------------------------------------------------------------- */
6897
0
    CPLString osType;
6898
0
    for (int i = iTypeIndex; i < nTokens; ++i)
6899
0
    {
6900
0
        osType += papszTokens[i];
6901
0
        CPLFree(papszTokens[i]);
6902
0
    }
6903
0
    char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6904
0
    papszTokens[iTypeIndex + 1] = nullptr;
6905
6906
    /* -------------------------------------------------------------------- */
6907
    /*      Find the named layer.                                           */
6908
    /* -------------------------------------------------------------------- */
6909
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6910
0
    if (poLayer == nullptr)
6911
0
    {
6912
0
        CPLError(CE_Failure, CPLE_AppDefined,
6913
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6914
0
                 pszLayerName);
6915
0
        CSLDestroy(papszTokens);
6916
0
        return OGRERR_FAILURE;
6917
0
    }
6918
6919
    /* -------------------------------------------------------------------- */
6920
    /*      Find the field.                                                 */
6921
    /* -------------------------------------------------------------------- */
6922
6923
0
    const int nFieldIndex =
6924
0
        poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6925
0
    if (nFieldIndex < 0)
6926
0
    {
6927
0
        CPLError(CE_Failure, CPLE_AppDefined,
6928
0
                 "%s failed, no such field as `%s'.", pszSQLCommand,
6929
0
                 pszColumnName);
6930
0
        CSLDestroy(papszTokens);
6931
0
        return OGRERR_FAILURE;
6932
0
    }
6933
6934
    /* -------------------------------------------------------------------- */
6935
    /*      Alter column.                                                   */
6936
    /* -------------------------------------------------------------------- */
6937
6938
0
    OGRFieldDefn *poOldFieldDefn =
6939
0
        poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6940
0
    OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6941
6942
0
    int nWidth = 0;
6943
0
    int nPrecision = 0;
6944
0
    OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6945
0
    oNewFieldDefn.SetType(eType);
6946
0
    oNewFieldDefn.SetWidth(nWidth);
6947
0
    oNewFieldDefn.SetPrecision(nPrecision);
6948
6949
0
    int l_nFlags = 0;
6950
0
    if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6951
0
        l_nFlags |= ALTER_TYPE_FLAG;
6952
0
    if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6953
0
        poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6954
0
        l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6955
6956
0
    CSLDestroy(papszTokens);
6957
6958
0
    if (l_nFlags == 0)
6959
0
        return OGRERR_NONE;
6960
6961
0
    return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6962
0
}
6963
6964
//! @endcond
6965
6966
/************************************************************************/
6967
/*                             ExecuteSQL()                             */
6968
/************************************************************************/
6969
6970
/**
6971
 \brief Execute an SQL statement against the data store.
6972
6973
 The result of an SQL query is either NULL for statements that are in error,
6974
 or that have no results set, or an OGRLayer pointer representing a results
6975
 set from the query.  Note that this OGRLayer is in addition to the layers
6976
 in the data store and must be destroyed with
6977
 ReleaseResultSet() before the dataset is closed
6978
 (destroyed).
6979
6980
 This method is the same as the C function GDALDatasetExecuteSQL() and the
6981
 deprecated OGR_DS_ExecuteSQL().
6982
6983
 For more information on the SQL dialect supported internally by OGR
6984
 review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
6985
 document.  Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
6986
 to the underlying RDBMS.
6987
6988
 Starting with OGR 1.10, the <a
6989
 href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
6990
 also be used.
6991
6992
 In GDAL 1.X, this method used to be in the OGRDataSource class.
6993
6994
 @param pszStatement the SQL statement to execute.
6995
 @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6996
 @param pszDialect allows control of the statement dialect. If set to NULL, the
6997
 OGR SQL engine will be used, except for RDBMS drivers that will use their
6998
 dedicated SQL engine, unless OGRSQL is explicitly passed as the
6999
 dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
7000
7001
 @return an OGRLayer containing the results of the query.  Deallocate with
7002
 ReleaseResultSet().
7003
7004
*/
7005
7006
OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
7007
                                  OGRGeometry *poSpatialFilter,
7008
                                  const char *pszDialect)
7009
7010
0
{
7011
0
    return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
7012
0
}
7013
7014
//! @cond Doxygen_Suppress
7015
OGRLayer *
7016
GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
7017
                        const char *pszDialect,
7018
                        swq_select_parse_options *poSelectParseOptions)
7019
7020
0
{
7021
0
    if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
7022
0
    {
7023
#ifdef SQLITE_ENABLED
7024
        return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
7025
                                   pszDialect);
7026
#else
7027
0
        CPLError(CE_Failure, CPLE_NotSupported,
7028
0
                 "The SQLite driver needs to be compiled to support the "
7029
0
                 "SQLite SQL dialect");
7030
0
        return nullptr;
7031
0
#endif
7032
0
    }
7033
7034
0
    if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
7035
0
        !EQUAL(pszDialect, "OGRSQL"))
7036
0
    {
7037
0
        std::string osDialectList = "'OGRSQL'";
7038
#ifdef SQLITE_ENABLED
7039
        osDialectList += ", 'SQLITE'";
7040
#endif
7041
0
        const char *pszDialects =
7042
0
            GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
7043
0
        if (pszDialects)
7044
0
        {
7045
0
            const CPLStringList aosTokens(
7046
0
                CSLTokenizeString2(pszDialects, " ", 0));
7047
0
            for (int i = 0; i < aosTokens.size(); ++i)
7048
0
            {
7049
0
                if (!EQUAL(aosTokens[i], "OGRSQL") &&
7050
0
                    !EQUAL(aosTokens[i], "SQLITE"))
7051
0
                {
7052
0
                    osDialectList += ", '";
7053
0
                    osDialectList += aosTokens[i];
7054
0
                    osDialectList += "'";
7055
0
                }
7056
0
            }
7057
0
        }
7058
0
        CPLError(CE_Warning, CPLE_NotSupported,
7059
0
                 "Dialect '%s' is unsupported. Only supported dialects are %s. "
7060
0
                 "Defaulting to OGRSQL",
7061
0
                 pszDialect, osDialectList.c_str());
7062
0
    }
7063
7064
    /* -------------------------------------------------------------------- */
7065
    /*      Handle CREATE INDEX statements specially.                       */
7066
    /* -------------------------------------------------------------------- */
7067
0
    if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
7068
0
    {
7069
0
        ProcessSQLCreateIndex(pszStatement);
7070
0
        return nullptr;
7071
0
    }
7072
7073
    /* -------------------------------------------------------------------- */
7074
    /*      Handle DROP INDEX statements specially.                         */
7075
    /* -------------------------------------------------------------------- */
7076
0
    if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
7077
0
    {
7078
0
        ProcessSQLDropIndex(pszStatement);
7079
0
        return nullptr;
7080
0
    }
7081
7082
    /* -------------------------------------------------------------------- */
7083
    /*      Handle DROP TABLE statements specially.                         */
7084
    /* -------------------------------------------------------------------- */
7085
0
    if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
7086
0
    {
7087
0
        ProcessSQLDropTable(pszStatement);
7088
0
        return nullptr;
7089
0
    }
7090
7091
    /* -------------------------------------------------------------------- */
7092
    /*      Handle ALTER TABLE statements specially.                        */
7093
    /* -------------------------------------------------------------------- */
7094
0
    if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
7095
0
    {
7096
0
        char **papszTokens = CSLTokenizeString(pszStatement);
7097
0
        const int nTokens = CSLCount(papszTokens);
7098
0
        if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
7099
0
        {
7100
0
            ProcessSQLAlterTableAddColumn(pszStatement);
7101
0
            CSLDestroy(papszTokens);
7102
0
            return nullptr;
7103
0
        }
7104
0
        else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
7105
0
        {
7106
0
            ProcessSQLAlterTableDropColumn(pszStatement);
7107
0
            CSLDestroy(papszTokens);
7108
0
            return nullptr;
7109
0
        }
7110
0
        else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
7111
0
                 EQUAL(papszTokens[4], "TO"))
7112
0
        {
7113
0
            const char *pszSrcTableName = papszTokens[2];
7114
0
            const char *pszDstTableName = papszTokens[5];
7115
0
            auto poSrcLayer = GetLayerByName(pszSrcTableName);
7116
0
            if (poSrcLayer)
7117
0
            {
7118
0
                CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
7119
0
            }
7120
0
            else
7121
0
            {
7122
0
                CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
7123
0
            }
7124
0
            CSLDestroy(papszTokens);
7125
0
            return nullptr;
7126
0
        }
7127
0
        else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
7128
0
        {
7129
0
            ProcessSQLAlterTableRenameColumn(pszStatement);
7130
0
            CSLDestroy(papszTokens);
7131
0
            return nullptr;
7132
0
        }
7133
0
        else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
7134
0
        {
7135
0
            ProcessSQLAlterTableAlterColumn(pszStatement);
7136
0
            CSLDestroy(papszTokens);
7137
0
            return nullptr;
7138
0
        }
7139
0
        else
7140
0
        {
7141
0
            CPLError(CE_Failure, CPLE_AppDefined,
7142
0
                     "Unsupported ALTER TABLE command : %s", pszStatement);
7143
0
            CSLDestroy(papszTokens);
7144
0
            return nullptr;
7145
0
        }
7146
0
    }
7147
7148
    /* -------------------------------------------------------------------- */
7149
    /*      Preparse the SQL statement.                                     */
7150
    /* -------------------------------------------------------------------- */
7151
0
    swq_select *psSelectInfo = new swq_select();
7152
0
    swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
7153
0
    if (poSelectParseOptions != nullptr)
7154
0
        poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
7155
0
    if (psSelectInfo->preparse(pszStatement,
7156
0
                               poCustomFuncRegistrar != nullptr) != CE_None)
7157
0
    {
7158
0
        delete psSelectInfo;
7159
0
        return nullptr;
7160
0
    }
7161
7162
    /* -------------------------------------------------------------------- */
7163
    /*      If there is no UNION ALL, build result layer.                   */
7164
    /* -------------------------------------------------------------------- */
7165
0
    if (psSelectInfo->poOtherSelect == nullptr)
7166
0
    {
7167
0
        return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
7168
0
                                        pszDialect, poSelectParseOptions);
7169
0
    }
7170
7171
    /* -------------------------------------------------------------------- */
7172
    /*      Build result union layer.                                       */
7173
    /* -------------------------------------------------------------------- */
7174
0
    int nSrcLayers = 0;
7175
0
    OGRLayer **papoSrcLayers = nullptr;
7176
7177
0
    do
7178
0
    {
7179
0
        swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
7180
0
        psSelectInfo->poOtherSelect = nullptr;
7181
7182
0
        OGRLayer *poLayer = BuildLayerFromSelectInfo(
7183
0
            psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
7184
0
        if (poLayer == nullptr)
7185
0
        {
7186
            // Each source layer owns an independent select info.
7187
0
            for (int i = 0; i < nSrcLayers; ++i)
7188
0
                delete papoSrcLayers[i];
7189
0
            CPLFree(papoSrcLayers);
7190
7191
            // So we just have to destroy the remaining select info.
7192
0
            delete psNextSelectInfo;
7193
7194
0
            return nullptr;
7195
0
        }
7196
0
        else
7197
0
        {
7198
0
            papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
7199
0
                papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
7200
0
            papoSrcLayers[nSrcLayers] = poLayer;
7201
0
            ++nSrcLayers;
7202
7203
0
            psSelectInfo = psNextSelectInfo;
7204
0
        }
7205
0
    } while (psSelectInfo != nullptr);
7206
7207
0
    return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
7208
0
}
7209
7210
//! @endcond
7211
7212
/************************************************************************/
7213
/*                             AbortSQL()                             */
7214
/************************************************************************/
7215
7216
/**
7217
 \brief Abort any SQL statement running in the data store.
7218
7219
 This function can be safely called from any thread (pending that the dataset
7220
 object is still alive). Driver implementations will make sure that it can be
7221
 called in a thread-safe way.
7222
7223
 This might not be implemented by all drivers. At time of writing, only SQLite,
7224
 GPKG and PG drivers implement it
7225
7226
 This method is the same as the C method GDALDatasetAbortSQL()
7227
7228
 @since GDAL 3.2.0
7229
7230
7231
*/
7232
7233
OGRErr GDALDataset::AbortSQL()
7234
0
{
7235
0
    CPLError(CE_Failure, CPLE_NotSupported,
7236
0
             "AbortSQL is not supported for this driver.");
7237
0
    return OGRERR_UNSUPPORTED_OPERATION;
7238
0
}
7239
7240
/************************************************************************/
7241
/*                        BuildLayerFromSelectInfo()                    */
7242
/************************************************************************/
7243
7244
struct GDALSQLParseInfo
7245
{
7246
    swq_field_list sFieldList;
7247
    int nExtraDSCount;
7248
    GDALDataset **papoExtraDS;
7249
    char *pszWHERE;
7250
};
7251
7252
OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7253
    swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7254
    const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7255
0
{
7256
0
    std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
7257
7258
0
    std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7259
0
    GDALSQLParseInfo *psParseInfo =
7260
0
        BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
7261
7262
0
    if (psParseInfo)
7263
0
    {
7264
0
        const auto nErrorCounter = CPLGetErrorCounter();
7265
0
        poResults = std::make_unique<OGRGenSQLResultsLayer>(
7266
0
            this, std::move(psSelectInfoUnique), poSpatialFilter,
7267
0
            psParseInfo->pszWHERE, pszDialect);
7268
0
        if (CPLGetErrorCounter() > nErrorCounter &&
7269
0
            CPLGetLastErrorType() != CE_None)
7270
0
            poResults.reset();
7271
0
    }
7272
7273
0
    DestroyParseInfo(psParseInfo);
7274
7275
0
    return poResults.release();
7276
0
}
7277
7278
/************************************************************************/
7279
/*                             DestroyParseInfo()                       */
7280
/************************************************************************/
7281
7282
//! @cond Doxygen_Suppress
7283
void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7284
0
{
7285
0
    if (psParseInfo == nullptr)
7286
0
        return;
7287
7288
0
    CPLFree(psParseInfo->sFieldList.names);
7289
0
    CPLFree(psParseInfo->sFieldList.types);
7290
0
    CPLFree(psParseInfo->sFieldList.table_ids);
7291
0
    CPLFree(psParseInfo->sFieldList.ids);
7292
7293
    // Release the datasets we have opened with OGROpenShared()
7294
    // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7295
    // has taken a reference on them, which it will release in its
7296
    // destructor.
7297
0
    for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7298
0
        GDALClose(psParseInfo->papoExtraDS[iEDS]);
7299
7300
0
    CPLFree(psParseInfo->papoExtraDS);
7301
0
    CPLFree(psParseInfo->pszWHERE);
7302
0
    CPLFree(psParseInfo);
7303
0
}
7304
7305
/************************************************************************/
7306
/*                            BuildParseInfo()                          */
7307
/************************************************************************/
7308
7309
GDALSQLParseInfo *
7310
GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7311
                            swq_select_parse_options *poSelectParseOptions)
7312
0
{
7313
0
    int nFirstLayerFirstSpecialFieldIndex = 0;
7314
7315
0
    GDALSQLParseInfo *psParseInfo =
7316
0
        static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7317
7318
    /* -------------------------------------------------------------------- */
7319
    /*      Validate that all the source tables are recognized, count       */
7320
    /*      fields.                                                         */
7321
    /* -------------------------------------------------------------------- */
7322
0
    int nFieldCount = 0;
7323
7324
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7325
0
    {
7326
0
        swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7327
0
        GDALDataset *poTableDS = this;
7328
7329
0
        if (psTableDef->data_source != nullptr)
7330
0
        {
7331
0
            poTableDS = GDALDataset::FromHandle(
7332
0
                OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7333
0
            if (poTableDS == nullptr)
7334
0
            {
7335
0
                if (strlen(CPLGetLastErrorMsg()) == 0)
7336
0
                    CPLError(CE_Failure, CPLE_AppDefined,
7337
0
                             "Unable to open secondary datasource "
7338
0
                             "`%s' required by JOIN.",
7339
0
                             psTableDef->data_source);
7340
7341
0
                DestroyParseInfo(psParseInfo);
7342
0
                return nullptr;
7343
0
            }
7344
7345
            // Keep in an array to release at the end of this function.
7346
0
            psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7347
0
                psParseInfo->papoExtraDS,
7348
0
                sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7349
0
            psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7350
0
        }
7351
7352
0
        OGRLayer *poSrcLayer =
7353
0
            poTableDS->GetLayerByName(psTableDef->table_name);
7354
7355
0
        if (poSrcLayer == nullptr)
7356
0
        {
7357
0
            CPLError(CE_Failure, CPLE_AppDefined,
7358
0
                     "SELECT from table %s failed, no such table/featureclass.",
7359
0
                     psTableDef->table_name);
7360
7361
0
            DestroyParseInfo(psParseInfo);
7362
0
            return nullptr;
7363
0
        }
7364
7365
0
        nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7366
0
        if (iTable == 0 ||
7367
0
            (poSelectParseOptions &&
7368
0
             poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7369
0
            nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7370
7371
0
        const char *pszFID = poSrcLayer->GetFIDColumn();
7372
0
        if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7373
0
            poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7374
0
            nFieldCount++;
7375
0
    }
7376
7377
    /* -------------------------------------------------------------------- */
7378
    /*      Build the field list for all indicated tables.                  */
7379
    /* -------------------------------------------------------------------- */
7380
7381
0
    psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7382
0
    psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7383
7384
0
    psParseInfo->sFieldList.count = 0;
7385
0
    psParseInfo->sFieldList.names = static_cast<char **>(
7386
0
        CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7387
0
    psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7388
0
        sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7389
0
    psParseInfo->sFieldList.table_ids = static_cast<int *>(
7390
0
        CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7391
0
    psParseInfo->sFieldList.ids = static_cast<int *>(
7392
0
        CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7393
7394
0
    bool bIsFID64 = false;
7395
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7396
0
    {
7397
0
        swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7398
0
        GDALDataset *poTableDS = this;
7399
7400
0
        if (psTableDef->data_source != nullptr)
7401
0
        {
7402
0
            poTableDS = GDALDataset::FromHandle(
7403
0
                OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7404
0
            CPLAssert(poTableDS != nullptr);
7405
0
            poTableDS->Dereference();
7406
0
        }
7407
7408
0
        OGRLayer *poSrcLayer =
7409
0
            poTableDS->GetLayerByName(psTableDef->table_name);
7410
7411
0
        for (int iField = 0;
7412
0
             iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7413
0
        {
7414
0
            OGRFieldDefn *poFDefn =
7415
0
                poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7416
0
            const int iOutField = psParseInfo->sFieldList.count++;
7417
0
            psParseInfo->sFieldList.names[iOutField] =
7418
0
                const_cast<char *>(poFDefn->GetNameRef());
7419
0
            if (poFDefn->GetType() == OFTInteger)
7420
0
            {
7421
0
                if (poFDefn->GetSubType() == OFSTBoolean)
7422
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7423
0
                else
7424
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7425
0
            }
7426
0
            else if (poFDefn->GetType() == OFTInteger64)
7427
0
            {
7428
0
                if (poFDefn->GetSubType() == OFSTBoolean)
7429
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7430
0
                else
7431
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7432
0
            }
7433
0
            else if (poFDefn->GetType() == OFTReal)
7434
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7435
0
            else if (poFDefn->GetType() == OFTString)
7436
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7437
0
            else if (poFDefn->GetType() == OFTTime)
7438
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7439
0
            else if (poFDefn->GetType() == OFTDate)
7440
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7441
0
            else if (poFDefn->GetType() == OFTDateTime)
7442
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7443
0
            else
7444
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7445
7446
0
            psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7447
0
            psParseInfo->sFieldList.ids[iOutField] = iField;
7448
0
        }
7449
7450
0
        if (iTable == 0)
7451
0
        {
7452
0
            nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7453
0
        }
7454
7455
0
        if (iTable == 0 ||
7456
0
            (poSelectParseOptions &&
7457
0
             poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7458
0
        {
7459
7460
0
            for (int iField = 0;
7461
0
                 iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7462
0
                 iField++)
7463
0
            {
7464
0
                OGRGeomFieldDefn *poFDefn =
7465
0
                    poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7466
0
                const int iOutField = psParseInfo->sFieldList.count++;
7467
0
                psParseInfo->sFieldList.names[iOutField] =
7468
0
                    const_cast<char *>(poFDefn->GetNameRef());
7469
0
                if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7470
0
                    psParseInfo->sFieldList.names[iOutField] =
7471
0
                        const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7472
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7473
7474
0
                psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7475
0
                psParseInfo->sFieldList.ids[iOutField] =
7476
0
                    GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7477
0
                        poSrcLayer->GetLayerDefn(), iField);
7478
0
            }
7479
0
        }
7480
7481
0
        if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7482
0
            EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7483
0
        {
7484
0
            bIsFID64 = true;
7485
0
        }
7486
0
    }
7487
7488
    /* -------------------------------------------------------------------- */
7489
    /*      Expand '*' in 'SELECT *' now before we add the pseudo fields    */
7490
    /* -------------------------------------------------------------------- */
7491
0
    const bool bAlwaysPrefixWithTableName =
7492
0
        poSelectParseOptions &&
7493
0
        poSelectParseOptions->bAlwaysPrefixWithTableName;
7494
0
    if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7495
0
                                      bAlwaysPrefixWithTableName) != CE_None)
7496
0
    {
7497
0
        DestroyParseInfo(psParseInfo);
7498
0
        return nullptr;
7499
0
    }
7500
7501
0
    for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7502
0
    {
7503
0
        psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7504
0
            const_cast<char *>(SpecialFieldNames[iField]);
7505
0
        psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7506
0
            (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7507
0
                                            : SpecialFieldTypes[iField];
7508
0
        psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7509
0
        psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7510
0
            nFirstLayerFirstSpecialFieldIndex + iField;
7511
0
        psParseInfo->sFieldList.count++;
7512
0
    }
7513
7514
    /* In the case a layer has an explicit FID column name, then add it */
7515
    /* so it can be selected */
7516
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7517
0
    {
7518
0
        swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7519
0
        GDALDataset *poTableDS = this;
7520
7521
0
        if (psTableDef->data_source != nullptr)
7522
0
        {
7523
0
            poTableDS = GDALDataset::FromHandle(
7524
0
                OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7525
0
            CPLAssert(poTableDS != nullptr);
7526
0
            poTableDS->Dereference();
7527
0
        }
7528
7529
0
        OGRLayer *poSrcLayer =
7530
0
            poTableDS->GetLayerByName(psTableDef->table_name);
7531
7532
0
        const char *pszFID = poSrcLayer->GetFIDColumn();
7533
0
        if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7534
0
            poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7535
0
        {
7536
0
            const int iOutField = psParseInfo->sFieldList.count++;
7537
0
            psParseInfo->sFieldList.names[iOutField] =
7538
0
                const_cast<char *>(pszFID);
7539
0
            if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7540
0
                EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7541
0
            {
7542
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7543
0
            }
7544
0
            else
7545
0
            {
7546
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7547
0
            }
7548
0
            psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7549
0
            psParseInfo->sFieldList.ids[iOutField] =
7550
0
                poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7551
0
        }
7552
0
    }
7553
7554
    /* -------------------------------------------------------------------- */
7555
    /*      Finish the parse operation.                                     */
7556
    /* -------------------------------------------------------------------- */
7557
0
    if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7558
0
        CE_None)
7559
0
    {
7560
0
        DestroyParseInfo(psParseInfo);
7561
0
        return nullptr;
7562
0
    }
7563
7564
    /* -------------------------------------------------------------------- */
7565
    /*      Extract the WHERE expression to use separately.                 */
7566
    /* -------------------------------------------------------------------- */
7567
0
    if (psSelectInfo->where_expr != nullptr)
7568
0
    {
7569
0
        psParseInfo->pszWHERE =
7570
0
            psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7571
        // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7572
0
    }
7573
7574
0
    return psParseInfo;
7575
0
}
7576
7577
//! @endcond
7578
7579
/************************************************************************/
7580
/*                          ReleaseResultSet()                          */
7581
/************************************************************************/
7582
7583
/**
7584
 \brief Release results of ExecuteSQL().
7585
7586
 This method should only be used to deallocate OGRLayers resulting from
7587
 an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
7588
 results set before destroying the GDALDataset may cause errors.
7589
7590
 This method is the same as the C function GDALDatasetReleaseResultSet() and the
7591
 deprecated OGR_DS_ReleaseResultSet().
7592
7593
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7594
7595
 @param poResultsSet the result of a previous ExecuteSQL() call.
7596
*/
7597
7598
void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7599
7600
0
{
7601
0
    delete poResultsSet;
7602
0
}
7603
7604
/************************************************************************/
7605
/*                            GetStyleTable()                           */
7606
/************************************************************************/
7607
7608
/**
7609
 \brief Returns dataset style table.
7610
7611
 This method is the same as the C function GDALDatasetGetStyleTable() and the
7612
 deprecated OGR_DS_GetStyleTable().
7613
7614
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7615
7616
 @return pointer to a style table which should not be modified or freed by the
7617
 caller.
7618
*/
7619
7620
OGRStyleTable *GDALDataset::GetStyleTable()
7621
0
{
7622
0
    return m_poStyleTable;
7623
0
}
7624
7625
/************************************************************************/
7626
/*                         SetStyleTableDirectly()                      */
7627
/************************************************************************/
7628
7629
/**
7630
 \brief Set dataset style table.
7631
7632
 This method operate exactly as SetStyleTable() except that it
7633
 assumes ownership of the passed table.
7634
7635
 This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7636
 and the deprecated OGR_DS_SetStyleTableDirectly().
7637
7638
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7639
7640
 @param poStyleTable pointer to style table to set
7641
7642
*/
7643
void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7644
0
{
7645
0
    if (m_poStyleTable)
7646
0
        delete m_poStyleTable;
7647
0
    m_poStyleTable = poStyleTable;
7648
0
}
7649
7650
/************************************************************************/
7651
/*                            SetStyleTable()                           */
7652
/************************************************************************/
7653
7654
/**
7655
 \brief Set dataset style table.
7656
7657
 This method operate exactly as SetStyleTableDirectly() except
7658
 that it does not assume ownership of the passed table.
7659
7660
 This method is the same as the C function GDALDatasetSetStyleTable() and the
7661
 deprecated OGR_DS_SetStyleTable().
7662
7663
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7664
7665
 @param poStyleTable pointer to style table to set
7666
7667
*/
7668
7669
void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7670
0
{
7671
0
    if (m_poStyleTable)
7672
0
        delete m_poStyleTable;
7673
0
    if (poStyleTable)
7674
0
        m_poStyleTable = poStyleTable->Clone();
7675
0
}
7676
7677
/************************************************************************/
7678
/*                         IsGenericSQLDialect()                        */
7679
/************************************************************************/
7680
7681
//! @cond Doxygen_Suppress
7682
int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7683
0
{
7684
0
    return pszDialect != nullptr &&
7685
0
           (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7686
0
}
7687
7688
//! @endcond
7689
7690
/************************************************************************/
7691
/*                            GetLayerCount()                           */
7692
/************************************************************************/
7693
7694
/**
7695
 \brief Get the number of layers in this dataset.
7696
7697
 This method is the same as the C function GDALDatasetGetLayerCount(),
7698
 and the deprecated OGR_DS_GetLayerCount().
7699
7700
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7701
7702
 @return layer count.
7703
*/
7704
7705
int GDALDataset::GetLayerCount()
7706
0
{
7707
0
    return 0;
7708
0
}
7709
7710
/************************************************************************/
7711
/*                                GetLayer()                            */
7712
/************************************************************************/
7713
7714
/**
7715
 \fn GDALDataset::GetLayer(int)
7716
 \brief Fetch a layer by index.
7717
7718
 The returned layer remains owned by the
7719
 GDALDataset and should not be deleted by the application.
7720
7721
 See GetLayers() for a C++ iterator version of this method.
7722
7723
 This method is the same as the C function GDALDatasetGetLayer() and the
7724
 deprecated OGR_DS_GetLayer().
7725
7726
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7727
7728
 @param iLayer a layer number between 0 and GetLayerCount()-1.
7729
7730
 @return the layer, or NULL if iLayer is out of range or an error occurs.
7731
7732
 @see GetLayers()
7733
*/
7734
7735
OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)
7736
0
{
7737
0
    return nullptr;
7738
0
}
7739
7740
/************************************************************************/
7741
/*                                IsLayerPrivate()                      */
7742
/************************************************************************/
7743
7744
/**
7745
 \fn GDALDataset::IsLayerPrivate(int)
7746
 \brief Returns true if the layer at the specified index is deemed a private or
7747
 system table, or an internal detail only.
7748
7749
 This method is the same as the C function GDALDatasetIsLayerPrivate().
7750
7751
 @param iLayer a layer number between 0 and GetLayerCount()-1.
7752
7753
 @return true if the layer is a private or system table.
7754
7755
 @since GDAL 3.4
7756
*/
7757
7758
bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7759
0
{
7760
0
    return false;
7761
0
}
7762
7763
/************************************************************************/
7764
/*                           ResetReading()                             */
7765
/************************************************************************/
7766
7767
/**
7768
 \brief Reset feature reading to start on the first feature.
7769
7770
 This affects GetNextFeature().
7771
7772
 Depending on drivers, this may also have the side effect of calling
7773
 OGRLayer::ResetReading() on the layers of this dataset.
7774
7775
 This method is the same as the C function GDALDatasetResetReading().
7776
7777
 @since GDAL 2.2
7778
*/
7779
void GDALDataset::ResetReading()
7780
0
{
7781
0
    if (!m_poPrivate)
7782
0
        return;
7783
0
    m_poPrivate->nCurrentLayerIdx = 0;
7784
0
    m_poPrivate->nLayerCount = -1;
7785
0
    m_poPrivate->poCurrentLayer = nullptr;
7786
0
    m_poPrivate->nFeatureReadInLayer = 0;
7787
0
    m_poPrivate->nFeatureReadInDataset = 0;
7788
0
    m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7789
0
    m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7790
0
}
7791
7792
/************************************************************************/
7793
/*                         GDALDatasetResetReading()                    */
7794
/************************************************************************/
7795
7796
/**
7797
 \brief Reset feature reading to start on the first feature.
7798
7799
 This affects GDALDatasetGetNextFeature().
7800
7801
 Depending on drivers, this may also have the side effect of calling
7802
 OGR_L_ResetReading() on the layers of this dataset.
7803
7804
 This method is the same as the C++ method GDALDataset::ResetReading()
7805
7806
 @param hDS dataset handle
7807
 @since GDAL 2.2
7808
*/
7809
void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7810
0
{
7811
0
    VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7812
7813
0
    return GDALDataset::FromHandle(hDS)->ResetReading();
7814
0
}
7815
7816
/************************************************************************/
7817
/*                          GetNextFeature()                            */
7818
/************************************************************************/
7819
7820
/**
7821
 \brief Fetch the next available feature from this dataset.
7822
7823
 This method is intended for the few drivers where OGRLayer::GetNextFeature()
7824
 is not efficient, but in general OGRLayer::GetNextFeature() is a more
7825
 natural API.
7826
7827
 See GetFeatures() for a C++ iterator version of this method.
7828
7829
 The returned feature becomes the responsibility of the caller to
7830
 delete with OGRFeature::DestroyFeature().
7831
7832
 Depending on the driver, this method may return features from layers in a
7833
 non sequential way. This is what may happen when the
7834
 ODsCRandomLayerRead capability is declared (for example for the
7835
 OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7836
 advised to use GDALDataset::GetNextFeature() instead of
7837
 OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7838
 implementation.
7839
7840
 The default implementation, used by most drivers, will
7841
 however iterate over each layer, and then over each feature within this
7842
 layer.
7843
7844
 This method takes into account spatial and attribute filters set on layers that
7845
 will be iterated upon.
7846
7847
 The ResetReading() method can be used to start at the beginning again.
7848
7849
 Depending on drivers, this may also have the side effect of calling
7850
 OGRLayer::GetNextFeature() on the layers of this dataset.
7851
7852
 This method is the same as the C function GDALDatasetGetNextFeature().
7853
7854
 @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
7855
                          layer to which the object belongs to, or NULL.
7856
                          It is possible that the output of *ppoBelongingLayer
7857
                          to be NULL despite the feature not being NULL.
7858
 @param pdfProgressPct    a pointer to a double variable to receive the
7859
                          percentage progress (in [0,1] range), or NULL.
7860
                          On return, the pointed value might be negative if
7861
                          determining the progress is not possible.
7862
 @param pfnProgress       a progress callback to report progress (for
7863
                          GetNextFeature() calls that might have a long
7864
                          duration) and offer cancellation possibility, or NULL.
7865
 @param pProgressData     user data provided to pfnProgress, or NULL
7866
 @return a feature, or NULL if no more features are available.
7867
 @since GDAL 2.2
7868
 @see GetFeatures()
7869
*/
7870
7871
OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
7872
                                        double *pdfProgressPct,
7873
                                        GDALProgressFunc pfnProgress,
7874
                                        void *pProgressData)
7875
0
{
7876
0
    if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
7877
0
    {
7878
0
        if (ppoBelongingLayer != nullptr)
7879
0
            *ppoBelongingLayer = nullptr;
7880
0
        if (pdfProgressPct != nullptr)
7881
0
            *pdfProgressPct = 1.0;
7882
0
        if (pfnProgress != nullptr)
7883
0
            pfnProgress(1.0, "", pProgressData);
7884
0
        return nullptr;
7885
0
    }
7886
7887
0
    if (m_poPrivate->poCurrentLayer == nullptr &&
7888
0
        (pdfProgressPct != nullptr || pfnProgress != nullptr))
7889
0
    {
7890
0
        if (m_poPrivate->nLayerCount < 0)
7891
0
        {
7892
0
            m_poPrivate->nLayerCount = GetLayerCount();
7893
0
        }
7894
7895
0
        if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
7896
0
        {
7897
0
            m_poPrivate->nTotalFeatures = 0;
7898
0
            for (int i = 0; i < m_poPrivate->nLayerCount; i++)
7899
0
            {
7900
0
                OGRLayer *poLayer = GetLayer(i);
7901
0
                if (poLayer == nullptr ||
7902
0
                    !poLayer->TestCapability(OLCFastFeatureCount))
7903
0
                {
7904
0
                    m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7905
0
                    break;
7906
0
                }
7907
0
                GIntBig nCount = poLayer->GetFeatureCount(FALSE);
7908
0
                if (nCount < 0)
7909
0
                {
7910
0
                    m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7911
0
                    break;
7912
0
                }
7913
0
                m_poPrivate->nTotalFeatures += nCount;
7914
0
            }
7915
0
        }
7916
0
    }
7917
7918
0
    while (true)
7919
0
    {
7920
0
        if (m_poPrivate->poCurrentLayer == nullptr)
7921
0
        {
7922
0
            m_poPrivate->poCurrentLayer =
7923
0
                GetLayer(m_poPrivate->nCurrentLayerIdx);
7924
0
            if (m_poPrivate->poCurrentLayer == nullptr)
7925
0
            {
7926
0
                m_poPrivate->nCurrentLayerIdx = -1;
7927
0
                if (ppoBelongingLayer != nullptr)
7928
0
                    *ppoBelongingLayer = nullptr;
7929
0
                if (pdfProgressPct != nullptr)
7930
0
                    *pdfProgressPct = 1.0;
7931
0
                return nullptr;
7932
0
            }
7933
0
            m_poPrivate->poCurrentLayer->ResetReading();
7934
0
            m_poPrivate->nFeatureReadInLayer = 0;
7935
0
            if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
7936
0
            {
7937
0
                if (m_poPrivate->poCurrentLayer->TestCapability(
7938
0
                        OLCFastFeatureCount))
7939
0
                    m_poPrivate->nTotalFeaturesInLayer =
7940
0
                        m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7941
0
                else
7942
0
                    m_poPrivate->nTotalFeaturesInLayer = 0;
7943
0
            }
7944
0
        }
7945
0
        OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7946
0
        if (poFeature == nullptr)
7947
0
        {
7948
0
            m_poPrivate->nCurrentLayerIdx++;
7949
0
            m_poPrivate->poCurrentLayer = nullptr;
7950
0
            continue;
7951
0
        }
7952
7953
0
        m_poPrivate->nFeatureReadInLayer++;
7954
0
        m_poPrivate->nFeatureReadInDataset++;
7955
0
        if (pdfProgressPct != nullptr || pfnProgress != nullptr)
7956
0
        {
7957
0
            double dfPct = 0.0;
7958
0
            if (m_poPrivate->nTotalFeatures > 0)
7959
0
            {
7960
0
                dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7961
0
                        m_poPrivate->nTotalFeatures;
7962
0
            }
7963
0
            else
7964
0
            {
7965
0
                dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
7966
0
                        m_poPrivate->nLayerCount;
7967
0
                if (m_poPrivate->nTotalFeaturesInLayer > 0)
7968
0
                {
7969
0
                    dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7970
0
                             m_poPrivate->nTotalFeaturesInLayer /
7971
0
                             m_poPrivate->nLayerCount;
7972
0
                }
7973
0
            }
7974
0
            if (pdfProgressPct)
7975
0
                *pdfProgressPct = dfPct;
7976
0
            if (pfnProgress)
7977
0
                pfnProgress(dfPct, "", nullptr);
7978
0
        }
7979
7980
0
        if (ppoBelongingLayer != nullptr)
7981
0
            *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7982
0
        return poFeature;
7983
0
    }
7984
0
}
7985
7986
/************************************************************************/
7987
/*                     GDALDatasetGetNextFeature()                      */
7988
/************************************************************************/
7989
/**
7990
 \brief Fetch the next available feature from this dataset.
7991
7992
 This method is intended for the few drivers where OGR_L_GetNextFeature()
7993
 is not efficient, but in general OGR_L_GetNextFeature() is a more
7994
 natural API.
7995
7996
 The returned feature becomes the responsibility of the caller to
7997
 delete with OGRFeature::DestroyFeature().
7998
7999
 Depending on the driver, this method may return features from layers in a
8000
 non sequential way. This is what may happen when the
8001
 ODsCRandomLayerRead capability is declared (for example for the
8002
 OSM and GMLAS drivers). When datasets declare this capability, it is strongly
8003
 advised to use GDALDataset::GetNextFeature() instead of
8004
 OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
8005
 implementation.
8006
8007
 The default implementation, used by most drivers, will
8008
 however iterate over each layer, and then over each feature within this
8009
 layer.
8010
8011
 This method takes into account spatial and attribute filters set on layers that
8012
 will be iterated upon.
8013
8014
 The ResetReading() method can be used to start at the beginning again.
8015
8016
 Depending on drivers, this may also have the side effect of calling
8017
 OGRLayer::GetNextFeature() on the layers of this dataset.
8018
8019
 This method is the same as the C++ method GDALDataset::GetNextFeature()
8020
8021
 @param hDS               dataset handle.
8022
 @param phBelongingLayer  a pointer to a OGRLayer* variable to receive the
8023
                          layer to which the object belongs to, or NULL.
8024
                          It is possible that the output of *ppoBelongingLayer
8025
                          to be NULL despite the feature not being NULL.
8026
 @param pdfProgressPct    a pointer to a double variable to receive the
8027
                          percentage progress (in [0,1] range), or NULL.
8028
                          On return, the pointed value might be negative if
8029
                          determining the progress is not possible.
8030
 @param pfnProgress       a progress callback to report progress (for
8031
                          GetNextFeature() calls that might have a long
8032
                          duration) and offer cancellation possibility, or NULL
8033
 @param pProgressData     user data provided to pfnProgress, or NULL
8034
 @return a feature, or NULL if no more features are available.
8035
 @since GDAL 2.2
8036
*/
8037
OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
8038
                                              OGRLayerH *phBelongingLayer,
8039
                                              double *pdfProgressPct,
8040
                                              GDALProgressFunc pfnProgress,
8041
                                              void *pProgressData)
8042
0
{
8043
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
8044
8045
0
    return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
8046
0
        reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
8047
0
        pfnProgress, pProgressData));
8048
0
}
8049
8050
/************************************************************************/
8051
/*                            TestCapability()                          */
8052
/************************************************************************/
8053
8054
/**
8055
 \fn GDALDataset::TestCapability( const char * pszCap )
8056
 \brief Test if capability is available.
8057
8058
 One of the following dataset capability names can be passed into this
8059
 method, and a TRUE or FALSE value will be returned indicating whether or not
8060
 the capability is available for this object.
8061
8062
 <ul>
8063
  <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
8064
  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
8065
          layers.<p>
8066
  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
8067
          datasource support CreateGeomField() just after layer creation.<p>
8068
  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
8069
          geometries.<p>
8070
  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
8071
          transactions.<p>
8072
  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
8073
          transactions through emulation.<p>
8074
  <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
8075
          GetNextFeature() implementation, potentially returning features from
8076
          layers in a non sequential way.<p>
8077
  <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
8078
         CreateFeature() on layers in a non sequential way.<p>
8079
  <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
8080
  <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
8081
  <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8082
  <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8083
  <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8084
 </ul>
8085
8086
 The \#define macro forms of the capability names should be used in preference
8087
 to the strings themselves to avoid misspelling.
8088
8089
 This method is the same as the C function GDALDatasetTestCapability() and the
8090
 deprecated OGR_DS_TestCapability().
8091
8092
 In GDAL 1.X, this method used to be in the OGRDataSource class.
8093
8094
 @param pszCap the capability to test.
8095
8096
 @return TRUE if capability available otherwise FALSE.
8097
*/
8098
8099
int GDALDataset::TestCapability(const char *pszCap)
8100
0
{
8101
0
    if (EQUAL(pszCap, GDsCFastGetExtent) ||
8102
0
        EQUAL(pszCap, GDsCFastGetExtentWGS84LongLat))
8103
0
    {
8104
0
        for (auto &&poLayer : GetLayers())
8105
0
        {
8106
0
            if (!poLayer->TestCapability(OLCFastGetExtent))
8107
0
                return FALSE;
8108
0
        }
8109
0
        return TRUE;
8110
0
    }
8111
0
    return FALSE;
8112
0
}
8113
8114
/************************************************************************/
8115
/*                     GDALDatasetTestCapability()                      */
8116
/************************************************************************/
8117
8118
/**
8119
 \brief Test if capability is available.
8120
8121
 One of the following dataset capability names can be passed into this
8122
 function, and a TRUE or FALSE value will be returned indicating whether or not
8123
 the capability is available for this object.
8124
8125
 <ul>
8126
  <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
8127
  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
8128
          layers.<p>
8129
  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
8130
          datasource support CreateGeomField() just after layer creation.<p>
8131
  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
8132
          geometries.<p>
8133
  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
8134
          transactions.<p>
8135
  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
8136
          transactions through emulation.<p>
8137
  <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
8138
          GetNextFeature() implementation, potentially returning features from
8139
          layers in a non sequential way.<p>
8140
  <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
8141
          CreateFeature() on layers in a non sequential way.<p>
8142
  <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
8143
  <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
8144
  <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8145
  <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8146
  <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8147
 </ul>
8148
8149
 The \#define macro forms of the capability names should be used in preference
8150
 to the strings themselves to avoid misspelling.
8151
8152
 This function is the same as the C++ method GDALDataset::TestCapability()
8153
8154
 @since GDAL 2.0
8155
8156
 @param hDS the dataset handle.
8157
 @param pszCap the capability to test.
8158
8159
 @return TRUE if capability available otherwise FALSE.
8160
*/
8161
int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
8162
8163
0
{
8164
0
    VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
8165
0
    VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
8166
8167
0
    return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
8168
0
}
8169
8170
/************************************************************************/
8171
/*                           StartTransaction()                         */
8172
/************************************************************************/
8173
8174
/**
8175
 \fn GDALDataset::StartTransaction(int)
8176
 \brief For datasources which support transactions, StartTransaction creates a
8177
`transaction.
8178
8179
 If starting the transaction fails, will return
8180
 OGRERR_FAILURE. Datasources which do not support transactions will
8181
 always return OGRERR_UNSUPPORTED_OPERATION.
8182
8183
 Nested transactions are not supported.
8184
8185
 All changes done after the start of the transaction are definitely applied in
8186
 the datasource if CommitTransaction() is called. They may be canceled by
8187
 calling RollbackTransaction() instead.
8188
8189
 At the time of writing, transactions only apply on vector layers.
8190
8191
 Datasets that support transactions will advertise the ODsCTransactions
8192
 capability.  Use of transactions at dataset level is generally preferred to
8193
 transactions at layer level, whose scope is rarely limited to the layer from
8194
 which it was started.
8195
8196
 In case StartTransaction() fails, neither CommitTransaction() or
8197
 RollbackTransaction() should be called.
8198
8199
 If an error occurs after a successful StartTransaction(), the whole transaction
8200
 may or may not be implicitly canceled, depending on drivers. (e.g.  the PG
8201
 driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
8202
 an explicit call to RollbackTransaction() should be done to keep things
8203
 balanced.
8204
8205
 By default, when bForce is set to FALSE, only "efficient" transactions will be
8206
 attempted. Some drivers may offer an emulation of transactions, but sometimes
8207
 with significant overhead, in which case the user must explicitly allow for
8208
 such an emulation by setting bForce to TRUE. Drivers that offer emulated
8209
 transactions should advertise the ODsCEmulatedTransactions capability (and not
8210
 ODsCTransactions).
8211
8212
 This function is the same as the C function GDALDatasetStartTransaction().
8213
8214
 @param bForce can be set to TRUE if an emulation, possibly slow, of a
8215
 transaction
8216
               mechanism is acceptable.
8217
8218
 @return OGRERR_NONE on success.
8219
 @since GDAL 2.0
8220
*/
8221
8222
OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
8223
0
{
8224
0
    return OGRERR_UNSUPPORTED_OPERATION;
8225
0
}
8226
8227
/************************************************************************/
8228
/*                      GDALDatasetStartTransaction()                   */
8229
/************************************************************************/
8230
8231
/**
8232
 \brief For datasources which support transactions, StartTransaction creates a
8233
 transaction.
8234
8235
 If starting the transaction fails, will return
8236
 OGRERR_FAILURE. Datasources which do not support transactions will
8237
 always return OGRERR_UNSUPPORTED_OPERATION.
8238
8239
 Nested transactions are not supported.
8240
8241
 All changes done after the start of the transaction are definitely applied in
8242
 the datasource if CommitTransaction() is called. They may be canceled by
8243
 calling RollbackTransaction() instead.
8244
8245
 At the time of writing, transactions only apply on vector layers.
8246
8247
 Datasets that support transactions will advertise the ODsCTransactions
8248
 capability.
8249
 Use of transactions at dataset level is generally preferred to transactions at
8250
 layer level, whose scope is rarely limited to the layer from which it was
8251
 started.
8252
8253
 In case StartTransaction() fails, neither CommitTransaction() or
8254
 RollbackTransaction() should be called.
8255
8256
 If an error occurs after a successful StartTransaction(), the whole
8257
 transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8258
 the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8259
 error, an explicit call to RollbackTransaction() should be done to keep things
8260
 balanced.
8261
8262
 By default, when bForce is set to FALSE, only "efficient" transactions will be
8263
 attempted. Some drivers may offer an emulation of transactions, but sometimes
8264
 with significant overhead, in which case the user must explicitly allow for
8265
 such an emulation by setting bForce to TRUE. Drivers that offer emulated
8266
 transactions should advertise the ODsCEmulatedTransactions capability (and not
8267
 ODsCTransactions).
8268
8269
 This function is the same as the C++ method GDALDataset::StartTransaction()
8270
8271
 @param hDS the dataset handle.
8272
 @param bForce can be set to TRUE if an emulation, possibly slow, of a
8273
 transaction
8274
               mechanism is acceptable.
8275
8276
 @return OGRERR_NONE on success.
8277
 @since GDAL 2.0
8278
*/
8279
OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8280
0
{
8281
0
    VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8282
0
                      OGRERR_INVALID_HANDLE);
8283
8284
0
#ifdef OGRAPISPY_ENABLED
8285
0
    if (bOGRAPISpyEnabled)
8286
0
        OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8287
0
#endif
8288
8289
0
    return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8290
0
}
8291
8292
/************************************************************************/
8293
/*                           CommitTransaction()                        */
8294
/************************************************************************/
8295
8296
/**
8297
 \brief For datasources which support transactions, CommitTransaction commits a
8298
 transaction.
8299
8300
 If no transaction is active, or the commit fails, will return
8301
 OGRERR_FAILURE. Datasources which do not support transactions will
8302
 always return OGRERR_UNSUPPORTED_OPERATION.
8303
8304
 Depending on drivers, this may or may not abort layer sequential readings that
8305
 are active.
8306
8307
 This function is the same as the C function GDALDatasetCommitTransaction().
8308
8309
 @return OGRERR_NONE on success.
8310
 @since GDAL 2.0
8311
*/
8312
OGRErr GDALDataset::CommitTransaction()
8313
0
{
8314
0
    return OGRERR_UNSUPPORTED_OPERATION;
8315
0
}
8316
8317
/************************************************************************/
8318
/*                        GDALDatasetCommitTransaction()                */
8319
/************************************************************************/
8320
8321
/**
8322
 \brief For datasources which support transactions, CommitTransaction commits a
8323
 transaction.
8324
8325
 If no transaction is active, or the commit fails, will return
8326
 OGRERR_FAILURE. Datasources which do not support transactions will
8327
 always return OGRERR_UNSUPPORTED_OPERATION.
8328
8329
 Depending on drivers, this may or may not abort layer sequential readings that
8330
 are active.
8331
8332
 This function is the same as the C++ method GDALDataset::CommitTransaction()
8333
8334
 @return OGRERR_NONE on success.
8335
 @since GDAL 2.0
8336
*/
8337
OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8338
0
{
8339
0
    VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8340
0
                      OGRERR_INVALID_HANDLE);
8341
8342
0
#ifdef OGRAPISPY_ENABLED
8343
0
    if (bOGRAPISpyEnabled)
8344
0
        OGRAPISpy_Dataset_CommitTransaction(hDS);
8345
0
#endif
8346
8347
0
    return GDALDataset::FromHandle(hDS)->CommitTransaction();
8348
0
}
8349
8350
/************************************************************************/
8351
/*                           RollbackTransaction()                      */
8352
/************************************************************************/
8353
8354
/**
8355
 \brief For datasources which support transactions, RollbackTransaction will
8356
 roll back a datasource to its state before the start of the current
8357
 transaction.
8358
 If no transaction is active, or the rollback fails, will return
8359
 OGRERR_FAILURE. Datasources which do not support transactions will
8360
 always return OGRERR_UNSUPPORTED_OPERATION.
8361
8362
 This function is the same as the C function GDALDatasetRollbackTransaction().
8363
8364
 @return OGRERR_NONE on success.
8365
 @since GDAL 2.0
8366
*/
8367
OGRErr GDALDataset::RollbackTransaction()
8368
0
{
8369
0
    return OGRERR_UNSUPPORTED_OPERATION;
8370
0
}
8371
8372
/************************************************************************/
8373
/*                     GDALDatasetRollbackTransaction()                 */
8374
/************************************************************************/
8375
8376
/**
8377
 \brief For datasources which support transactions, RollbackTransaction will
8378
 roll back a datasource to its state before the start of the current
8379
 transaction.
8380
 If no transaction is active, or the rollback fails, will return
8381
 OGRERR_FAILURE. Datasources which do not support transactions will
8382
 always return OGRERR_UNSUPPORTED_OPERATION.
8383
8384
 This function is the same as the C++ method GDALDataset::RollbackTransaction().
8385
8386
 @return OGRERR_NONE on success.
8387
 @since GDAL 2.0
8388
*/
8389
OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8390
0
{
8391
0
    VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8392
0
                      OGRERR_INVALID_HANDLE);
8393
8394
0
#ifdef OGRAPISPY_ENABLED
8395
0
    if (bOGRAPISpyEnabled)
8396
0
        OGRAPISpy_Dataset_RollbackTransaction(hDS);
8397
0
#endif
8398
8399
0
    return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8400
0
}
8401
8402
//! @cond Doxygen_Suppress
8403
8404
/************************************************************************/
8405
/*                   ShareLockWithParentDataset()                       */
8406
/************************************************************************/
8407
8408
/* To be used typically by the GTiff driver to link overview datasets */
8409
/* with their main dataset, so that they share the same lock */
8410
/* Cf https://github.com/OSGeo/gdal/issues/1488 */
8411
/* The parent dataset should remain alive while the this dataset is alive */
8412
8413
void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8414
0
{
8415
0
    if (m_poPrivate != nullptr)
8416
0
    {
8417
0
        m_poPrivate->poParentDataset = poParentDataset;
8418
0
    }
8419
0
}
8420
8421
/************************************************************************/
8422
/*                   SetQueryLoggerFunc()                               */
8423
/************************************************************************/
8424
8425
bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8426
                                     CPL_UNUSED void *context)
8427
0
{
8428
0
    return false;
8429
0
}
8430
8431
/************************************************************************/
8432
/*                          EnterReadWrite()                            */
8433
/************************************************************************/
8434
8435
int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8436
0
{
8437
0
    if (m_poPrivate == nullptr ||
8438
0
        IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
8439
0
        return FALSE;
8440
8441
0
    if (m_poPrivate->poParentDataset)
8442
0
        return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8443
8444
0
    if (eAccess == GA_Update)
8445
0
    {
8446
0
        if (m_poPrivate->eStateReadWriteMutex ==
8447
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8448
0
        {
8449
            // In case dead-lock would occur, which is not impossible,
8450
            // this can be used to prevent it, but at the risk of other
8451
            // issues.
8452
0
            if (CPLTestBool(
8453
0
                    CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8454
0
            {
8455
0
                m_poPrivate->eStateReadWriteMutex =
8456
0
                    GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8457
0
            }
8458
0
            else
8459
0
            {
8460
0
                m_poPrivate->eStateReadWriteMutex =
8461
0
                    GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8462
0
            }
8463
0
        }
8464
0
        if (m_poPrivate->eStateReadWriteMutex ==
8465
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8466
0
        {
8467
            // There should be no race related to creating this mutex since
8468
            // it should be first created through IWriteBlock() / IRasterIO()
8469
            // and then GDALRasterBlock might call it from another thread.
8470
#ifdef DEBUG_VERBOSE
8471
            CPLDebug("GDAL",
8472
                     "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8473
                     CPLGetPID(), GetDescription());
8474
#endif
8475
0
            CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8476
8477
0
            const int nCountMutex =
8478
0
                m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8479
0
            if (nCountMutex == 0 && eRWFlag == GF_Read)
8480
0
            {
8481
0
                CPLReleaseMutex(m_poPrivate->hMutex);
8482
0
                for (int i = 0; i < nBands; i++)
8483
0
                {
8484
0
                    auto blockCache = papoBands[i]->poBandBlockCache;
8485
0
                    if (blockCache)
8486
0
                        blockCache->WaitCompletionPendingTasks();
8487
0
                }
8488
0
                CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8489
0
            }
8490
8491
0
            return TRUE;
8492
0
        }
8493
0
    }
8494
0
    return FALSE;
8495
0
}
8496
8497
/************************************************************************/
8498
/*                         LeaveReadWrite()                             */
8499
/************************************************************************/
8500
8501
void GDALDataset::LeaveReadWrite()
8502
0
{
8503
0
    if (m_poPrivate)
8504
0
    {
8505
0
        if (m_poPrivate->poParentDataset)
8506
0
        {
8507
0
            m_poPrivate->poParentDataset->LeaveReadWrite();
8508
0
            return;
8509
0
        }
8510
8511
0
        m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8512
0
        CPLReleaseMutex(m_poPrivate->hMutex);
8513
#ifdef DEBUG_VERBOSE
8514
        CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8515
                 CPLGetPID(), GetDescription());
8516
#endif
8517
0
    }
8518
0
}
8519
8520
/************************************************************************/
8521
/*                           InitRWLock()                               */
8522
/************************************************************************/
8523
8524
void GDALDataset::InitRWLock()
8525
0
{
8526
0
    if (m_poPrivate)
8527
0
    {
8528
0
        if (m_poPrivate->poParentDataset)
8529
0
        {
8530
0
            m_poPrivate->poParentDataset->InitRWLock();
8531
0
            return;
8532
0
        }
8533
8534
0
        if (m_poPrivate->eStateReadWriteMutex ==
8535
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8536
0
        {
8537
0
            if (EnterReadWrite(GF_Write))
8538
0
                LeaveReadWrite();
8539
0
        }
8540
0
    }
8541
0
}
8542
8543
/************************************************************************/
8544
/*                       DisableReadWriteMutex()                        */
8545
/************************************************************************/
8546
8547
// The mutex logic is broken in multi-threaded situations, for example
8548
// with 2 WarpedVRT datasets being read at the same time. In that
8549
// particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8550
// to disable it.
8551
void GDALDataset::DisableReadWriteMutex()
8552
0
{
8553
0
    if (m_poPrivate)
8554
0
    {
8555
0
        if (m_poPrivate->poParentDataset)
8556
0
        {
8557
0
            m_poPrivate->poParentDataset->DisableReadWriteMutex();
8558
0
            return;
8559
0
        }
8560
8561
0
        m_poPrivate->eStateReadWriteMutex =
8562
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8563
0
    }
8564
0
}
8565
8566
/************************************************************************/
8567
/*                      TemporarilyDropReadWriteLock()                  */
8568
/************************************************************************/
8569
8570
void GDALDataset::TemporarilyDropReadWriteLock()
8571
0
{
8572
0
    if (m_poPrivate == nullptr)
8573
0
        return;
8574
8575
0
    if (m_poPrivate->poParentDataset)
8576
0
    {
8577
0
        m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8578
0
        return;
8579
0
    }
8580
8581
0
#ifndef __COVERITY__
8582
0
    if (m_poPrivate->hMutex)
8583
0
    {
8584
#ifdef DEBUG_VERBOSE
8585
        CPLDebug("GDAL",
8586
                 "[Thread " CPL_FRMT_GIB "] "
8587
                 "Temporarily drop RW mutex for %s",
8588
                 CPLGetPID(), GetDescription());
8589
#endif
8590
0
        CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8591
0
        const int nCount =
8592
0
            m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8593
#ifdef DEBUG_EXTRA
8594
        m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8595
#endif
8596
0
        for (int i = 0; i < nCount + 1; i++)
8597
0
        {
8598
            // The mutex is recursive
8599
0
            CPLReleaseMutex(m_poPrivate->hMutex);
8600
0
        }
8601
0
    }
8602
0
#endif
8603
0
}
8604
8605
/************************************************************************/
8606
/*                       ReacquireReadWriteLock()                       */
8607
/************************************************************************/
8608
8609
void GDALDataset::ReacquireReadWriteLock()
8610
0
{
8611
0
    if (m_poPrivate == nullptr)
8612
0
        return;
8613
8614
0
    if (m_poPrivate->poParentDataset)
8615
0
    {
8616
0
        m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8617
0
        return;
8618
0
    }
8619
8620
0
#ifndef __COVERITY__
8621
0
    if (m_poPrivate->hMutex)
8622
0
    {
8623
#ifdef DEBUG_VERBOSE
8624
        CPLDebug("GDAL",
8625
                 "[Thread " CPL_FRMT_GIB "] "
8626
                 "Reacquire temporarily dropped RW mutex for %s",
8627
                 CPLGetPID(), GetDescription());
8628
#endif
8629
0
        CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8630
0
        const int nCount =
8631
0
            m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8632
#ifdef DEBUG_EXTRA
8633
        CPLAssert(nCount ==
8634
                  m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8635
#endif
8636
0
        if (nCount == 0)
8637
0
            CPLReleaseMutex(m_poPrivate->hMutex);
8638
0
        for (int i = 0; i < nCount - 1; i++)
8639
0
        {
8640
            // The mutex is recursive
8641
0
            CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8642
0
        }
8643
0
    }
8644
0
#endif
8645
0
}
8646
8647
/************************************************************************/
8648
/*                           AcquireMutex()                             */
8649
/************************************************************************/
8650
8651
int GDALDataset::AcquireMutex()
8652
0
{
8653
0
    if (m_poPrivate == nullptr)
8654
0
        return 0;
8655
0
    if (m_poPrivate->poParentDataset)
8656
0
    {
8657
0
        return m_poPrivate->poParentDataset->AcquireMutex();
8658
0
    }
8659
8660
0
    return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8661
0
}
8662
8663
/************************************************************************/
8664
/*                          ReleaseMutex()                              */
8665
/************************************************************************/
8666
8667
void GDALDataset::ReleaseMutex()
8668
0
{
8669
0
    if (m_poPrivate)
8670
0
    {
8671
0
        if (m_poPrivate->poParentDataset)
8672
0
        {
8673
0
            m_poPrivate->poParentDataset->ReleaseMutex();
8674
0
            return;
8675
0
        }
8676
8677
0
        CPLReleaseMutex(m_poPrivate->hMutex);
8678
0
    }
8679
0
}
8680
8681
//! @endcond
8682
8683
/************************************************************************/
8684
/*              GDALDataset::Features::Iterator::Private                */
8685
/************************************************************************/
8686
8687
struct GDALDataset::Features::Iterator::Private
8688
{
8689
    GDALDataset::FeatureLayerPair m_oPair{};
8690
    GDALDataset *m_poDS = nullptr;
8691
    bool m_bEOF = true;
8692
};
8693
8694
GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8695
0
    : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8696
0
{
8697
0
    m_poPrivate->m_poDS = poDS;
8698
0
    if (bStart)
8699
0
    {
8700
0
        poDS->ResetReading();
8701
0
        m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8702
0
            &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8703
0
        m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8704
0
    }
8705
0
}
8706
8707
0
GDALDataset::Features::Iterator::~Iterator() = default;
8708
8709
const GDALDataset::FeatureLayerPair &
8710
GDALDataset::Features::Iterator::operator*() const
8711
0
{
8712
0
    return m_poPrivate->m_oPair;
8713
0
}
8714
8715
GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8716
0
{
8717
0
    m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8718
0
        &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8719
0
    m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8720
0
    return *this;
8721
0
}
8722
8723
bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8724
0
{
8725
0
    return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8726
0
}
8727
8728
/************************************************************************/
8729
/*                            GetFeatures()                             */
8730
/************************************************************************/
8731
8732
/** Function that return an iterable object over features in the dataset
8733
 * layer.
8734
 *
8735
 * This is a C++ iterator friendly version of GetNextFeature().
8736
 *
8737
 * Using this iterator for standard range-based loops is safe, but
8738
 * due to implementation limitations, you shouldn't try to access
8739
 * (dereference) more than one iterator step at a time, since the
8740
 * FeatureLayerPair reference which is returned is reused.
8741
 *
8742
 * Typical use is:
8743
 * \code{.cpp}
8744
 * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8745
 * {
8746
 *       std::cout << "Feature of layer " <<
8747
 *               oFeatureLayerPair.layer->GetName() << std::endl;
8748
 *       oFeatureLayerPair.feature->DumpReadable();
8749
 * }
8750
 * \endcode
8751
 *
8752
 * @see GetNextFeature()
8753
 *
8754
 * @since GDAL 2.3
8755
 */
8756
GDALDataset::Features GDALDataset::GetFeatures()
8757
0
{
8758
0
    return Features(this);
8759
0
}
8760
8761
/************************************************************************/
8762
/*                                 begin()                              */
8763
/************************************************************************/
8764
8765
/**
8766
 \brief Return beginning of feature iterator.
8767
8768
 @since GDAL 2.3
8769
*/
8770
8771
const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8772
0
{
8773
0
    return {m_poSelf, true};
8774
0
}
8775
8776
/************************************************************************/
8777
/*                                  end()                               */
8778
/************************************************************************/
8779
8780
/**
8781
 \brief Return end of feature iterator.
8782
8783
 @since GDAL 2.3
8784
*/
8785
8786
const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8787
0
{
8788
0
    return {m_poSelf, false};
8789
0
}
8790
8791
/************************************************************************/
8792
/*               GDALDataset::Layers::Iterator::Private                 */
8793
/************************************************************************/
8794
8795
struct GDALDataset::Layers::Iterator::Private
8796
{
8797
    OGRLayer *m_poLayer = nullptr;
8798
    int m_iCurLayer = 0;
8799
    int m_nLayerCount = 0;
8800
    GDALDataset *m_poDS = nullptr;
8801
};
8802
8803
0
GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8804
0
{
8805
0
}
8806
8807
// False positive of cppcheck 1.72
8808
// cppcheck-suppress uninitMemberVar
8809
GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8810
0
    : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8811
0
{
8812
0
}
8813
8814
GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
8815
0
    : m_poPrivate(std::move(oOther.m_poPrivate))
8816
0
{
8817
0
}
8818
8819
GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8820
0
    : m_poPrivate(new Private())
8821
0
{
8822
0
    m_poPrivate->m_poDS = poDS;
8823
0
    m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
8824
0
    if (bStart)
8825
0
    {
8826
0
        if (m_poPrivate->m_nLayerCount)
8827
0
            m_poPrivate->m_poLayer = poDS->GetLayer(0);
8828
0
    }
8829
0
    else
8830
0
    {
8831
0
        m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
8832
0
    }
8833
0
}
8834
8835
0
GDALDataset::Layers::Iterator::~Iterator() = default;
8836
8837
// False positive of cppcheck 1.72
8838
// cppcheck-suppress operatorEqVarError
8839
GDALDataset::Layers::Iterator &
8840
GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
8841
0
{
8842
0
    *m_poPrivate = *oOther.m_poPrivate;
8843
0
    return *this;
8844
0
}
8845
8846
GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
8847
    GDALDataset::Layers::Iterator &&oOther) noexcept
8848
0
{
8849
0
    m_poPrivate = std::move(oOther.m_poPrivate);
8850
0
    return *this;
8851
0
}
8852
8853
OGRLayer *GDALDataset::Layers::Iterator::operator*() const
8854
0
{
8855
0
    return m_poPrivate->m_poLayer;
8856
0
}
8857
8858
GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
8859
0
{
8860
0
    m_poPrivate->m_iCurLayer++;
8861
0
    if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
8862
0
    {
8863
0
        m_poPrivate->m_poLayer =
8864
0
            m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
8865
0
    }
8866
0
    else
8867
0
    {
8868
0
        m_poPrivate->m_poLayer = nullptr;
8869
0
    }
8870
0
    return *this;
8871
0
}
8872
8873
GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
8874
0
{
8875
0
    GDALDataset::Layers::Iterator temp = *this;
8876
0
    ++(*this);
8877
0
    return temp;
8878
0
}
8879
8880
bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
8881
0
{
8882
0
    return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
8883
0
}
8884
8885
/************************************************************************/
8886
/*                             GetLayers()                              */
8887
/************************************************************************/
8888
8889
/** Function that returns an iterable object over layers in the dataset.
8890
 *
8891
 * This is a C++ iterator friendly version of GetLayer().
8892
 *
8893
 * Typical use is:
8894
 * \code{.cpp}
8895
 * for( auto&& poLayer: poDS->GetLayers() )
8896
 * {
8897
 *       std::cout << "Layer  << poLayer->GetName() << std::endl;
8898
 * }
8899
 * \endcode
8900
 *
8901
 * @see GetLayer()
8902
 *
8903
 * @since GDAL 2.3
8904
 */
8905
GDALDataset::Layers GDALDataset::GetLayers()
8906
0
{
8907
0
    return Layers(this);
8908
0
}
8909
8910
/************************************************************************/
8911
/*                                 begin()                              */
8912
/************************************************************************/
8913
8914
/**
8915
 \brief Return beginning of layer iterator.
8916
8917
 @since GDAL 2.3
8918
*/
8919
8920
GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
8921
0
{
8922
0
    return {m_poSelf, true};
8923
0
}
8924
8925
/************************************************************************/
8926
/*                                  end()                               */
8927
/************************************************************************/
8928
8929
/**
8930
 \brief Return end of layer iterator.
8931
8932
 @since GDAL 2.3
8933
*/
8934
8935
GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
8936
0
{
8937
0
    return {m_poSelf, false};
8938
0
}
8939
8940
/************************************************************************/
8941
/*                                  size()                             */
8942
/************************************************************************/
8943
8944
/**
8945
 \brief Get the number of layers in this dataset.
8946
8947
 @return layer count.
8948
8949
 @since GDAL 2.3
8950
*/
8951
8952
size_t GDALDataset::Layers::size() const
8953
0
{
8954
0
    return static_cast<size_t>(m_poSelf->GetLayerCount());
8955
0
}
8956
8957
/************************************************************************/
8958
/*                                operator[]()                          */
8959
/************************************************************************/
8960
/**
8961
 \brief Fetch a layer by index.
8962
8963
 The returned layer remains owned by the
8964
 GDALDataset and should not be deleted by the application.
8965
8966
 @param iLayer a layer number between 0 and size()-1.
8967
8968
 @return the layer, or nullptr if iLayer is out of range or an error occurs.
8969
8970
 @since GDAL 2.3
8971
*/
8972
8973
OGRLayer *GDALDataset::Layers::operator[](int iLayer)
8974
0
{
8975
0
    return m_poSelf->GetLayer(iLayer);
8976
0
}
8977
8978
/************************************************************************/
8979
/*                                operator[]()                          */
8980
/************************************************************************/
8981
/**
8982
 \brief Fetch a layer by index.
8983
8984
 The returned layer remains owned by the
8985
 GDALDataset and should not be deleted by the application.
8986
8987
 @param iLayer a layer number between 0 and size()-1.
8988
8989
 @return the layer, or nullptr if iLayer is out of range or an error occurs.
8990
8991
 @since GDAL 2.3
8992
*/
8993
8994
OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
8995
0
{
8996
0
    return m_poSelf->GetLayer(static_cast<int>(iLayer));
8997
0
}
8998
8999
/************************************************************************/
9000
/*                                operator[]()                          */
9001
/************************************************************************/
9002
/**
9003
 \brief Fetch a layer by name.
9004
9005
 The returned layer remains owned by the
9006
 GDALDataset and should not be deleted by the application.
9007
9008
 @param pszLayerName layer name
9009
9010
 @return the layer, or nullptr if pszLayerName does not match with a layer
9011
9012
 @since GDAL 2.3
9013
*/
9014
9015
OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
9016
0
{
9017
0
    return m_poSelf->GetLayerByName(pszLayerName);
9018
0
}
9019
9020
/************************************************************************/
9021
/*               GDALDataset::Bands::Iterator::Private                 */
9022
/************************************************************************/
9023
9024
struct GDALDataset::Bands::Iterator::Private
9025
{
9026
    GDALRasterBand *m_poBand = nullptr;
9027
    int m_iCurBand = 0;
9028
    int m_nBandCount = 0;
9029
    GDALDataset *m_poDS = nullptr;
9030
};
9031
9032
GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
9033
0
    : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
9034
0
{
9035
0
    m_poPrivate->m_poDS = poDS;
9036
0
    m_poPrivate->m_nBandCount = poDS->GetRasterCount();
9037
0
    if (bStart)
9038
0
    {
9039
0
        if (m_poPrivate->m_nBandCount)
9040
0
            m_poPrivate->m_poBand = poDS->GetRasterBand(1);
9041
0
    }
9042
0
    else
9043
0
    {
9044
0
        m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
9045
0
    }
9046
0
}
9047
9048
0
GDALDataset::Bands::Iterator::~Iterator() = default;
9049
9050
GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
9051
0
{
9052
0
    return m_poPrivate->m_poBand;
9053
0
}
9054
9055
GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
9056
0
{
9057
0
    m_poPrivate->m_iCurBand++;
9058
0
    if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
9059
0
    {
9060
0
        m_poPrivate->m_poBand =
9061
0
            m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
9062
0
    }
9063
0
    else
9064
0
    {
9065
0
        m_poPrivate->m_poBand = nullptr;
9066
0
    }
9067
0
    return *this;
9068
0
}
9069
9070
bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
9071
0
{
9072
0
    return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
9073
0
}
9074
9075
/************************************************************************/
9076
/*                            GetBands()                           */
9077
/************************************************************************/
9078
9079
/** Function that returns an iterable object over GDALRasterBand in the dataset.
9080
 *
9081
 * This is a C++ iterator friendly version of GetRasterBand().
9082
 *
9083
 * Typical use is:
9084
 * \code{.cpp}
9085
 * for( auto&& poBand: poDS->GetBands() )
9086
 * {
9087
 *       std::cout << "Band  << poBand->GetDescription() << std::endl;
9088
 * }
9089
 * \endcode
9090
 *
9091
 * @see GetRasterBand()
9092
 *
9093
 * @since GDAL 2.3
9094
 */
9095
GDALDataset::Bands GDALDataset::GetBands()
9096
0
{
9097
0
    return Bands(this);
9098
0
}
9099
9100
/************************************************************************/
9101
/*                                 begin()                              */
9102
/************************************************************************/
9103
9104
/**
9105
 \brief Return beginning of band iterator.
9106
9107
 @since GDAL 2.3
9108
*/
9109
9110
const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
9111
0
{
9112
0
    return {m_poSelf, true};
9113
0
}
9114
9115
/************************************************************************/
9116
/*                                  end()                               */
9117
/************************************************************************/
9118
9119
/**
9120
 \brief Return end of band iterator.
9121
9122
 @since GDAL 2.3
9123
*/
9124
9125
const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
9126
0
{
9127
0
    return {m_poSelf, false};
9128
0
}
9129
9130
/************************************************************************/
9131
/*                                  size()                             */
9132
/************************************************************************/
9133
9134
/**
9135
 \brief Get the number of raster bands in this dataset.
9136
9137
 @return raster band count.
9138
9139
 @since GDAL 2.3
9140
*/
9141
9142
size_t GDALDataset::Bands::size() const
9143
0
{
9144
0
    return static_cast<size_t>(m_poSelf->GetRasterCount());
9145
0
}
9146
9147
/************************************************************************/
9148
/*                                operator[]()                          */
9149
/************************************************************************/
9150
/**
9151
 \brief Fetch a raster band by index.
9152
9153
 The returned band remains owned by the
9154
 GDALDataset and should not be deleted by the application.
9155
9156
 @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9157
 consistent with the conventions of C/C++, i.e. starting at 0.
9158
9159
 @param iBand a band index between 0 and size()-1.
9160
9161
 @return the band, or nullptr if iBand is out of range or an error occurs.
9162
9163
 @since GDAL 2.3
9164
*/
9165
9166
GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
9167
0
{
9168
0
    return m_poSelf->GetRasterBand(1 + iBand);
9169
0
}
9170
9171
/************************************************************************/
9172
/*                                operator[]()                          */
9173
/************************************************************************/
9174
9175
/**
9176
 \brief Fetch a raster band by index.
9177
9178
 The returned band remains owned by the
9179
 GDALDataset and should not be deleted by the application.
9180
9181
 @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9182
 consistent with the conventions of C/C++, i.e. starting at 0.
9183
9184
 @param iBand a band index between 0 and size()-1.
9185
9186
 @return the band, or nullptr if iBand is out of range or an error occurs.
9187
9188
 @since GDAL 2.3
9189
*/
9190
9191
GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
9192
0
{
9193
0
    return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9194
0
}
9195
9196
/************************************************************************/
9197
/*                           GetRootGroup()                             */
9198
/************************************************************************/
9199
9200
/**
9201
 \brief Return the root GDALGroup of this dataset.
9202
9203
 Only valid for multidimensional datasets.
9204
9205
 This is the same as the C function GDALDatasetGetRootGroup().
9206
9207
 @since GDAL 3.1
9208
*/
9209
9210
std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
9211
0
{
9212
0
    return nullptr;
9213
0
}
9214
9215
/************************************************************************/
9216
/*                        GetRawBinaryLayout()                          */
9217
/************************************************************************/
9218
9219
//! @cond Doxygen_Suppress
9220
/**
9221
 \brief Return the layout of a dataset that can be considered as a raw binary
9222
 format.
9223
9224
 @param sLayout Structure that will be set if the dataset is a raw binary one.
9225
 @return true if the dataset is a raw binary one.
9226
 @since GDAL 3.1
9227
*/
9228
9229
bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
9230
0
{
9231
0
    CPL_IGNORE_RET_VAL(sLayout);
9232
0
    return false;
9233
0
}
9234
9235
//! @endcond
9236
9237
/************************************************************************/
9238
/*                          ClearStatistics()                           */
9239
/************************************************************************/
9240
9241
/**
9242
 \brief Clear statistics
9243
9244
 Only implemented for now in PAM supported datasets
9245
9246
 This is the same as the C function GDALDatasetClearStatistics().
9247
9248
 @since GDAL 3.2
9249
*/
9250
9251
void GDALDataset::ClearStatistics()
9252
0
{
9253
0
    auto poRootGroup = GetRootGroup();
9254
0
    if (poRootGroup)
9255
0
        poRootGroup->ClearStatistics();
9256
0
}
9257
9258
/************************************************************************/
9259
/*                        GDALDatasetClearStatistics()                  */
9260
/************************************************************************/
9261
9262
/**
9263
 \brief Clear statistics
9264
9265
 This is the same as the C++ method GDALDataset::ClearStatistics().
9266
9267
 @since GDAL 3.2
9268
*/
9269
9270
void GDALDatasetClearStatistics(GDALDatasetH hDS)
9271
0
{
9272
0
    VALIDATE_POINTER0(hDS, __func__);
9273
0
    GDALDataset::FromHandle(hDS)->ClearStatistics();
9274
0
}
9275
9276
/************************************************************************/
9277
/*                        GetFieldDomainNames()                         */
9278
/************************************************************************/
9279
9280
/** Returns a list of the names of all field domains stored in the dataset.
9281
 *
9282
 * @note The default implementation assumes that drivers fully populate
9283
 * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9284
 * then a specialized implementation of GetFieldDomainNames() must be
9285
 * implemented.
9286
 *
9287
 * @param papszOptions Driver specific options determining how attributes
9288
 * should be retrieved. Pass nullptr for default behavior.
9289
 *
9290
 * @return list of field domain names
9291
 * @since GDAL 3.5
9292
 */
9293
std::vector<std::string>
9294
GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9295
0
{
9296
9297
0
    std::vector<std::string> names;
9298
0
    names.reserve(m_oMapFieldDomains.size());
9299
0
    for (const auto &it : m_oMapFieldDomains)
9300
0
    {
9301
0
        names.emplace_back(it.first);
9302
0
    }
9303
0
    return names;
9304
0
}
9305
9306
/************************************************************************/
9307
/*                      GDALDatasetGetFieldDomainNames()                */
9308
/************************************************************************/
9309
9310
/** Returns a list of the names of all field domains stored in the dataset.
9311
 *
9312
 * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9313
 *
9314
 * @param hDS Dataset handle.
9315
 * @param papszOptions Driver specific options determining how attributes
9316
 * should be retrieved. Pass nullptr for default behavior.
9317
 *
9318
 * @return list of field domain names, to be freed with CSLDestroy()
9319
 * @since GDAL 3.5
9320
 */
9321
char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9322
                                      CSLConstList papszOptions)
9323
0
{
9324
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9325
0
    auto names =
9326
0
        GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9327
0
    CPLStringList res;
9328
0
    for (const auto &name : names)
9329
0
    {
9330
0
        res.AddString(name.c_str());
9331
0
    }
9332
0
    return res.StealList();
9333
0
}
9334
9335
/************************************************************************/
9336
/*                        GetFieldDomain()                              */
9337
/************************************************************************/
9338
9339
/** Get a field domain from its name.
9340
 *
9341
 * @return the field domain, or nullptr if not found.
9342
 * @since GDAL 3.3
9343
 */
9344
const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9345
0
{
9346
0
    const auto iter = m_oMapFieldDomains.find(name);
9347
0
    if (iter == m_oMapFieldDomains.end())
9348
0
        return nullptr;
9349
0
    return iter->second.get();
9350
0
}
9351
9352
/************************************************************************/
9353
/*                      GDALDatasetGetFieldDomain()                     */
9354
/************************************************************************/
9355
9356
/** Get a field domain from its name.
9357
 *
9358
 * This is the same as the C++ method GDALDataset::GetFieldDomain().
9359
 *
9360
 * @param hDS Dataset handle.
9361
 * @param pszName Name of field domain.
9362
 * @return the field domain (ownership remains to the dataset), or nullptr if
9363
 * not found.
9364
 * @since GDAL 3.3
9365
 */
9366
OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9367
0
{
9368
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9369
0
    VALIDATE_POINTER1(pszName, __func__, nullptr);
9370
0
    return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9371
0
        GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9372
0
}
9373
9374
/************************************************************************/
9375
/*                         AddFieldDomain()                             */
9376
/************************************************************************/
9377
9378
/** Add a field domain to the dataset.
9379
 *
9380
 * Only a few drivers will support this operation, and some of them might only
9381
 * support it only for some types of field domains.
9382
 * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9383
 * support this operation. A dataset having at least some support for this
9384
 * operation should report the ODsCAddFieldDomain dataset capability.
9385
 *
9386
 * Anticipated failures will not be emitted through the CPLError()
9387
 * infrastructure, but will be reported in the failureReason output parameter.
9388
 *
9389
 * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9390
 * default implementation of GetFieldDomainNames() to work correctly, or
9391
 * alternatively a specialized implementation of GetFieldDomainNames() should be
9392
 * implemented.
9393
 *
9394
 * @param domain The domain definition.
9395
 * @param failureReason      Output parameter. Will contain an error message if
9396
 *                           an error occurs.
9397
 * @return true in case of success.
9398
 * @since GDAL 3.3
9399
 */
9400
bool GDALDataset::AddFieldDomain(
9401
    CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9402
    std::string &failureReason)
9403
0
{
9404
0
    failureReason = "AddFieldDomain not supported by this driver";
9405
0
    return false;
9406
0
}
9407
9408
/************************************************************************/
9409
/*                     GDALDatasetAddFieldDomain()                      */
9410
/************************************************************************/
9411
9412
/** Add a field domain to the dataset.
9413
 *
9414
 * Only a few drivers will support this operation, and some of them might only
9415
 * support it only for some types of field domains.
9416
 * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9417
 * support this operation. A dataset having at least some support for this
9418
 * operation should report the ODsCAddFieldDomain dataset capability.
9419
 *
9420
 * Anticipated failures will not be emitted through the CPLError()
9421
 * infrastructure, but will be reported in the ppszFailureReason output
9422
 * parameter.
9423
 *
9424
 * @param hDS                Dataset handle.
9425
 * @param hFieldDomain       The domain definition. Contrary to the C++ version,
9426
 *                           the passed object is copied.
9427
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9428
 *                           an error occurs (*ppszFailureReason to be freed
9429
 *                           with CPLFree). May be NULL.
9430
 * @return true in case of success.
9431
 * @since GDAL 3.3
9432
 */
9433
bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9434
                               char **ppszFailureReason)
9435
0
{
9436
0
    VALIDATE_POINTER1(hDS, __func__, false);
9437
0
    VALIDATE_POINTER1(hFieldDomain, __func__, false);
9438
0
    auto poDomain = std::unique_ptr<OGRFieldDomain>(
9439
0
        OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9440
0
    if (poDomain == nullptr)
9441
0
        return false;
9442
0
    std::string failureReason;
9443
0
    const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9444
0
        std::move(poDomain), failureReason);
9445
0
    if (ppszFailureReason)
9446
0
    {
9447
0
        *ppszFailureReason =
9448
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9449
0
    }
9450
0
    return bRet;
9451
0
}
9452
9453
/************************************************************************/
9454
/*                        DeleteFieldDomain()                           */
9455
/************************************************************************/
9456
9457
/** Removes a field domain from the dataset.
9458
 *
9459
 * Only a few drivers will support this operation.
9460
 *
9461
 * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9462
 * support this operation. A dataset having at least some support for this
9463
 * operation should report the ODsCDeleteFieldDomain dataset capability.
9464
 *
9465
 * Anticipated failures will not be emitted through the CPLError()
9466
 * infrastructure, but will be reported in the failureReason output parameter.
9467
 *
9468
 * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9469
 * default implementation of GetFieldDomainNames() to work correctly, or
9470
 * alternatively a specialized implementation of GetFieldDomainNames() should be
9471
 * implemented.
9472
 *
9473
 * @param name The domain name.
9474
 * @param failureReason      Output parameter. Will contain an error message if
9475
 *                           an error occurs.
9476
 * @return true in case of success.
9477
 * @since GDAL 3.5
9478
 */
9479
bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
9480
                                    std::string &failureReason)
9481
0
{
9482
0
    failureReason = "DeleteFieldDomain not supported by this driver";
9483
0
    return false;
9484
0
}
9485
9486
/************************************************************************/
9487
/*                  GDALDatasetDeleteFieldDomain()                      */
9488
/************************************************************************/
9489
9490
/** Removes a field domain from the dataset.
9491
 *
9492
 * Only a few drivers will support this operation.
9493
 *
9494
 * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9495
 * support this operation. A dataset having at least some support for this
9496
 * operation should report the ODsCDeleteFieldDomain dataset capability.
9497
 *
9498
 * Anticipated failures will not be emitted through the CPLError()
9499
 * infrastructure, but will be reported in the ppszFailureReason output
9500
 * parameter.
9501
 *
9502
 * @param hDS                Dataset handle.
9503
 * @param pszName            The domain name.
9504
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9505
 *                           an error occurs (*ppszFailureReason to be freed
9506
 *                           with CPLFree). May be NULL.
9507
 * @return true in case of success.
9508
 * @since GDAL 3.3
9509
 */
9510
bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
9511
                                  char **ppszFailureReason)
9512
0
{
9513
0
    VALIDATE_POINTER1(hDS, __func__, false);
9514
0
    VALIDATE_POINTER1(pszName, __func__, false);
9515
0
    std::string failureReason;
9516
0
    const bool bRet =
9517
0
        GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
9518
0
    if (ppszFailureReason)
9519
0
    {
9520
0
        *ppszFailureReason =
9521
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9522
0
    }
9523
0
    return bRet;
9524
0
}
9525
9526
/************************************************************************/
9527
/*                       UpdateFieldDomain()                            */
9528
/************************************************************************/
9529
9530
/** Updates an existing field domain by replacing its definition.
9531
 *
9532
 * The existing field domain with matching name will be replaced.
9533
 *
9534
 * Only a few drivers will support this operation, and some of them might only
9535
 * support it only for some types of field domains.
9536
 * At the time of writing (GDAL 3.5), only the Memory driver
9537
 * supports this operation. A dataset having at least some support for this
9538
 * operation should report the ODsCUpdateFieldDomain dataset capability.
9539
 *
9540
 * Anticipated failures will not be emitted through the CPLError()
9541
 * infrastructure, but will be reported in the failureReason output parameter.
9542
 *
9543
 * @param domain The domain definition.
9544
 * @param failureReason      Output parameter. Will contain an error message if
9545
 *                           an error occurs.
9546
 * @return true in case of success.
9547
 * @since GDAL 3.5
9548
 */
9549
bool GDALDataset::UpdateFieldDomain(
9550
    CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9551
    std::string &failureReason)
9552
0
{
9553
0
    failureReason = "UpdateFieldDomain not supported by this driver";
9554
0
    return false;
9555
0
}
9556
9557
/************************************************************************/
9558
/*                  GDALDatasetUpdateFieldDomain()                      */
9559
/************************************************************************/
9560
9561
/** Updates an existing field domain by replacing its definition.
9562
 *
9563
 * The existing field domain with matching name will be replaced.
9564
 *
9565
 * Only a few drivers will support this operation, and some of them might only
9566
 * support it only for some types of field domains.
9567
 * At the time of writing (GDAL 3.5), only the Memory driver
9568
 * supports this operation. A dataset having at least some support for this
9569
 * operation should report the ODsCUpdateFieldDomain dataset capability.
9570
 *
9571
 * Anticipated failures will not be emitted through the CPLError()
9572
 * infrastructure, but will be reported in the failureReason output parameter.
9573
 *
9574
 * @param hDS                Dataset handle.
9575
 * @param hFieldDomain       The domain definition. Contrary to the C++ version,
9576
 *                           the passed object is copied.
9577
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9578
 *                           an error occurs (*ppszFailureReason to be freed
9579
 *                           with CPLFree). May be NULL.
9580
 * @return true in case of success.
9581
 * @since GDAL 3.5
9582
 */
9583
bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
9584
                                  OGRFieldDomainH hFieldDomain,
9585
                                  char **ppszFailureReason)
9586
0
{
9587
0
    VALIDATE_POINTER1(hDS, __func__, false);
9588
0
    VALIDATE_POINTER1(hFieldDomain, __func__, false);
9589
0
    auto poDomain = std::unique_ptr<OGRFieldDomain>(
9590
0
        OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9591
0
    if (poDomain == nullptr)
9592
0
        return false;
9593
0
    std::string failureReason;
9594
0
    const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
9595
0
        std::move(poDomain), failureReason);
9596
0
    if (ppszFailureReason)
9597
0
    {
9598
0
        *ppszFailureReason =
9599
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9600
0
    }
9601
0
    return bRet;
9602
0
}
9603
9604
/************************************************************************/
9605
/*                        GetRelationshipNames()                        */
9606
/************************************************************************/
9607
9608
/** Returns a list of the names of all relationships stored in the dataset.
9609
 *
9610
 * @param papszOptions Driver specific options determining how relationships
9611
 * should be retrieved. Pass nullptr for default behavior.
9612
 *
9613
 * @return list of relationship names
9614
 * @since GDAL 3.6
9615
 */
9616
std::vector<std::string>
9617
GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
9618
0
{
9619
0
    return {};
9620
0
}
9621
9622
/************************************************************************/
9623
/*                     GDALDatasetGetRelationshipNames()                */
9624
/************************************************************************/
9625
9626
/** Returns a list of the names of all relationships stored in the dataset.
9627
 *
9628
 * This is the same as the C++ method GDALDataset::GetRelationshipNames().
9629
 *
9630
 * @param hDS Dataset handle.
9631
 * @param papszOptions Driver specific options determining how relationships
9632
 * should be retrieved. Pass nullptr for default behavior.
9633
 *
9634
 * @return list of relationship names, to be freed with CSLDestroy()
9635
 * @since GDAL 3.6
9636
 */
9637
char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
9638
                                       CSLConstList papszOptions)
9639
0
{
9640
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9641
0
    auto names =
9642
0
        GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
9643
0
    CPLStringList res;
9644
0
    for (const auto &name : names)
9645
0
    {
9646
0
        res.AddString(name.c_str());
9647
0
    }
9648
0
    return res.StealList();
9649
0
}
9650
9651
/************************************************************************/
9652
/*                        GetRelationship()                             */
9653
/************************************************************************/
9654
9655
/** Get a relationship from its name.
9656
 *
9657
 * @return the relationship, or nullptr if not found.
9658
 * @since GDAL 3.6
9659
 */
9660
const GDALRelationship *
9661
GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
9662
0
{
9663
0
    return nullptr;
9664
0
}
9665
9666
/************************************************************************/
9667
/*                      GDALDatasetGetRelationship()                    */
9668
/************************************************************************/
9669
9670
/** Get a relationship from its name.
9671
 *
9672
 * This is the same as the C++ method GDALDataset::GetRelationship().
9673
 *
9674
 * @param hDS Dataset handle.
9675
 * @param pszName Name of relationship.
9676
 * @return the relationship (ownership remains to the dataset), or nullptr if
9677
 * not found.
9678
 * @since GDAL 3.6
9679
 */
9680
GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
9681
                                             const char *pszName)
9682
0
{
9683
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9684
0
    VALIDATE_POINTER1(pszName, __func__, nullptr);
9685
0
    return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
9686
0
        GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
9687
0
}
9688
9689
/************************************************************************/
9690
/*                         AddRelationship()                            */
9691
/************************************************************************/
9692
9693
/** Add a relationship to the dataset.
9694
 *
9695
 * Only a few drivers will support this operation, and some of them might only
9696
 * support it only for some types of relationships.
9697
 *
9698
 * A dataset having at least some support for this
9699
 * operation should report the GDsCAddRelationship dataset capability.
9700
 *
9701
 * Anticipated failures will not be emitted through the CPLError()
9702
 * infrastructure, but will be reported in the failureReason output parameter.
9703
 *
9704
 * When adding a many-to-many relationship
9705
 * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9706
 * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
9707
 * the driver to create an appropriately named and structured mapping table.
9708
 * Some dataset formats require particular naming conventions and field
9709
 * structures for the mapping table, and delegating the construction of the
9710
 * mapping table to the driver will avoid these pitfalls.
9711
 *
9712
 * @param relationship The relationship definition.
9713
 * @param failureReason      Output parameter. Will contain an error message if
9714
 *                           an error occurs.
9715
 * @return true in case of success.
9716
 * @since GDAL 3.6
9717
 */
9718
bool GDALDataset::AddRelationship(
9719
    CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9720
    std::string &failureReason)
9721
0
{
9722
0
    failureReason = "AddRelationship not supported by this driver";
9723
0
    return false;
9724
0
}
9725
9726
/************************************************************************/
9727
/*                     GDALDatasetAddRelationship()                     */
9728
/************************************************************************/
9729
9730
/** Add a relationship to the dataset.
9731
 *
9732
 * Only a few drivers will support this operation, and some of them might only
9733
 * support it only for some types of relationships.
9734
 *
9735
 * A dataset having at least some support for this
9736
 * operation should report the GDsCAddRelationship dataset capability.
9737
 *
9738
 * Anticipated failures will not be emitted through the CPLError()
9739
 * infrastructure, but will be reported in the failureReason output parameter.
9740
 *
9741
 * When adding a many-to-many relationship
9742
 * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9743
 * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
9744
 * driver to create an appropriately named and structured mapping table. Some
9745
 * dataset formats require particular naming conventions and field structures
9746
 * for the mapping table, and delegating the construction of the mapping table
9747
 * to the driver will avoid these pitfalls.
9748
 *
9749
 * @param hDS                Dataset handle.
9750
 * @param hRelationship      The relationship definition. Contrary to the C++
9751
 * version, the passed object is copied.
9752
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9753
 *                           an error occurs (*ppszFailureReason to be freed
9754
 *                           with CPLFree). May be NULL.
9755
 * @return true in case of success.
9756
 * @since GDAL 3.6
9757
 */
9758
bool GDALDatasetAddRelationship(GDALDatasetH hDS,
9759
                                GDALRelationshipH hRelationship,
9760
                                char **ppszFailureReason)
9761
0
{
9762
0
    VALIDATE_POINTER1(hDS, __func__, false);
9763
0
    VALIDATE_POINTER1(hRelationship, __func__, false);
9764
0
    std::unique_ptr<GDALRelationship> poRelationship(
9765
0
        new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9766
0
    std::string failureReason;
9767
0
    const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
9768
0
        std::move(poRelationship), failureReason);
9769
0
    if (ppszFailureReason)
9770
0
    {
9771
0
        *ppszFailureReason =
9772
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9773
0
    }
9774
0
    return bRet;
9775
0
}
9776
9777
/************************************************************************/
9778
/*                        DeleteRelationship()                          */
9779
/************************************************************************/
9780
9781
/** Removes a relationship from the dataset.
9782
 *
9783
 * Only a few drivers will support this operation.
9784
 *
9785
 * A dataset having at least some support for this
9786
 * operation should report the GDsCDeleteRelationship dataset capability.
9787
 *
9788
 * Anticipated failures will not be emitted through the CPLError()
9789
 * infrastructure, but will be reported in the failureReason output parameter.
9790
 *
9791
 * @param name The relationship name.
9792
 * @param failureReason      Output parameter. Will contain an error message if
9793
 *                           an error occurs.
9794
 * @return true in case of success.
9795
 * @since GDAL 3.6
9796
 */
9797
bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
9798
                                     std::string &failureReason)
9799
0
{
9800
0
    failureReason = "DeleteRelationship not supported by this driver";
9801
0
    return false;
9802
0
}
9803
9804
/************************************************************************/
9805
/*                  GDALDatasetDeleteRelationship()                     */
9806
/************************************************************************/
9807
9808
/** Removes a relationship from the dataset.
9809
 *
9810
 * Only a few drivers will support this operation.
9811
 *
9812
 * A dataset having at least some support for this
9813
 * operation should report the GDsCDeleteRelationship dataset capability.
9814
 *
9815
 * Anticipated failures will not be emitted through the CPLError()
9816
 * infrastructure, but will be reported in the ppszFailureReason output
9817
 * parameter.
9818
 *
9819
 * @param hDS                Dataset handle.
9820
 * @param pszName            The relationship name.
9821
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9822
 *                           an error occurs (*ppszFailureReason to be freed
9823
 *                           with CPLFree). May be NULL.
9824
 * @return true in case of success.
9825
 * @since GDAL 3.6
9826
 */
9827
bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
9828
                                   char **ppszFailureReason)
9829
0
{
9830
0
    VALIDATE_POINTER1(hDS, __func__, false);
9831
0
    VALIDATE_POINTER1(pszName, __func__, false);
9832
0
    std::string failureReason;
9833
0
    const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
9834
0
        pszName, failureReason);
9835
0
    if (ppszFailureReason)
9836
0
    {
9837
0
        *ppszFailureReason =
9838
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9839
0
    }
9840
0
    return bRet;
9841
0
}
9842
9843
/************************************************************************/
9844
/*                       UpdateRelationship()                           */
9845
/************************************************************************/
9846
9847
/** Updates an existing relationship by replacing its definition.
9848
 *
9849
 * The existing relationship with matching name will be replaced.
9850
 *
9851
 * Only a few drivers will support this operation, and some of them might only
9852
 * support it only for some types of relationships.
9853
 * A dataset having at least some support for this
9854
 * operation should report the GDsCUpdateRelationship dataset capability.
9855
 *
9856
 * Anticipated failures will not be emitted through the CPLError()
9857
 * infrastructure, but will be reported in the failureReason output parameter.
9858
 *
9859
 * @param relationship   The relationship definition.
9860
 * @param failureReason  Output parameter. Will contain an error message if
9861
 *                       an error occurs.
9862
 * @return true in case of success.
9863
 * @since GDAL 3.6
9864
 */
9865
bool GDALDataset::UpdateRelationship(
9866
    CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9867
    std::string &failureReason)
9868
0
{
9869
0
    failureReason = "UpdateRelationship not supported by this driver";
9870
0
    return false;
9871
0
}
9872
9873
/************************************************************************/
9874
/*                  GDALDatasetUpdateRelationship()                     */
9875
/************************************************************************/
9876
9877
/** Updates an existing relationship by replacing its definition.
9878
 *
9879
 * The existing relationship with matching name will be replaced.
9880
 *
9881
 * Only a few drivers will support this operation, and some of them might only
9882
 * support it only for some types of relationships.
9883
 * A dataset having at least some support for this
9884
 * operation should report the GDsCUpdateRelationship dataset capability.
9885
 *
9886
 * Anticipated failures will not be emitted through the CPLError()
9887
 * infrastructure, but will be reported in the failureReason output parameter.
9888
 *
9889
 * @param hDS                Dataset handle.
9890
 * @param hRelationship      The relationship definition. Contrary to the C++
9891
 * version, the passed object is copied.
9892
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9893
 *                           an error occurs (*ppszFailureReason to be freed
9894
 *                           with CPLFree). May be NULL.
9895
 * @return true in case of success.
9896
 * @since GDAL 3.5
9897
 */
9898
bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
9899
                                   GDALRelationshipH hRelationship,
9900
                                   char **ppszFailureReason)
9901
0
{
9902
0
    VALIDATE_POINTER1(hDS, __func__, false);
9903
0
    VALIDATE_POINTER1(hRelationship, __func__, false);
9904
0
    std::unique_ptr<GDALRelationship> poRelationship(
9905
0
        new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9906
0
    std::string failureReason;
9907
0
    const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
9908
0
        std::move(poRelationship), failureReason);
9909
0
    if (ppszFailureReason)
9910
0
    {
9911
0
        *ppszFailureReason =
9912
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9913
0
    }
9914
0
    return bRet;
9915
0
}
9916
9917
/************************************************************************/
9918
/*                  GDALDatasetSetQueryLoggerFunc()                     */
9919
/************************************************************************/
9920
9921
/**
9922
 * Sets the SQL query logger callback.
9923
 *
9924
 * When supported by the driver, the callback will be called with
9925
 * the executed SQL text, the error message, the execution time in milliseconds,
9926
 * the number of records fetched/affected and the client status data.
9927
 *
9928
 * A value of -1 in the execution time or in the number of records indicates
9929
 * that the values are unknown.
9930
 *
9931
 * @param hDS                   Dataset handle.
9932
 * @param pfnQueryLoggerFunc    Callback function
9933
 * @param poQueryLoggerArg      Opaque client status data
9934
 * @return                      true in case of success.
9935
 * @since                       GDAL 3.7
9936
 */
9937
bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
9938
                                   GDALQueryLoggerFunc pfnQueryLoggerFunc,
9939
                                   void *poQueryLoggerArg)
9940
0
{
9941
0
    VALIDATE_POINTER1(hDS, __func__, false);
9942
0
    return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
9943
0
                                                            poQueryLoggerArg);
9944
0
}
9945
9946
//! @cond Doxygen_Suppress
9947
9948
/************************************************************************/
9949
/*                       SetEnableOverviews()                           */
9950
/************************************************************************/
9951
9952
void GDALDataset::SetEnableOverviews(bool bEnable)
9953
0
{
9954
0
    if (m_poPrivate)
9955
0
    {
9956
0
        m_poPrivate->m_bOverviewsEnabled = bEnable;
9957
0
    }
9958
0
}
9959
9960
/************************************************************************/
9961
/*                      AreOverviewsEnabled()                           */
9962
/************************************************************************/
9963
9964
bool GDALDataset::AreOverviewsEnabled() const
9965
0
{
9966
0
    return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
9967
0
}
9968
9969
/************************************************************************/
9970
/*                             IsAllBands()                             */
9971
/************************************************************************/
9972
9973
bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
9974
0
{
9975
0
    if (nBands != nBandCount)
9976
0
        return false;
9977
0
    if (panBandList)
9978
0
    {
9979
0
        for (int i = 0; i < nBandCount; ++i)
9980
0
        {
9981
0
            if (panBandList[i] != i + 1)
9982
0
                return false;
9983
0
        }
9984
0
    }
9985
0
    return true;
9986
0
}
9987
9988
//! @endcond
9989
9990
/************************************************************************/
9991
/*                       GetCompressionFormats()                        */
9992
/************************************************************************/
9993
9994
/** Return the compression formats that can be natively obtained for the
9995
 * window of interest and requested bands.
9996
 *
9997
 * For example, a tiled dataset may be able to return data in a compressed
9998
 * format if the window of interest matches exactly a tile. For some formats,
9999
 * drivers may also be able to merge several tiles together (not currently
10000
 * implemented though).
10001
 *
10002
 * Each format string is a pseudo MIME type, whose first part can be passed
10003
 * as the pszFormat argument of ReadCompressedData(), with additional
10004
 * parameters specified as key=value with a semi-colon separator.
10005
 *
10006
 * The amount and types of optional parameters passed after the MIME type is
10007
 * format dependent, and driver dependent (some drivers might not be able to
10008
 * return those extra information without doing a rather costly processing).
10009
 *
10010
 * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
10011
 * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
10012
 * consequently "JPEG" can be passed as the pszFormat argument of
10013
 * ReadCompressedData(). For JPEG, implementations can use the
10014
 * GDALGetCompressionFormatForJPEG() helper method to generate a string like
10015
 * above from a JPEG codestream.
10016
 *
10017
 * Several values might be returned. For example,
10018
 * the JPEGXL driver will return "JXL", but also potentially "JPEG"
10019
 * if the JPEGXL codestream includes a JPEG reconstruction box.
10020
 *
10021
 * In the general case this method will return an empty list.
10022
 *
10023
 * This is the same as C function GDALDatasetGetCompressionFormats().
10024
 *
10025
 * @param nXOff The pixel offset to the top left corner of the region
10026
 * of the band to be accessed.  This would be zero to start from the left side.
10027
 *
10028
 * @param nYOff The line offset to the top left corner of the region
10029
 * of the band to be accessed.  This would be zero to start from the top.
10030
 *
10031
 * @param nXSize The width of the region of the band to be accessed in pixels.
10032
 *
10033
 * @param nYSize The height of the region of the band to be accessed in lines.
10034
 *
10035
 * @param nBandCount the number of bands being requested.
10036
 *
10037
 * @param panBandList the list of nBandCount band numbers.
10038
 * Note band numbers are 1 based. This may be NULL to select the first
10039
 * nBandCount bands.
10040
 *
10041
 * @return a list of compatible formats (which may be empty)
10042
 *
10043
 * For example, to check if native compression format(s) are available on the
10044
 * whole image:
10045
 * \code{.cpp}
10046
 *   const CPLStringList aosFormats =
10047
 *      poDataset->GetCompressionFormats(0, 0,
10048
 *                                       poDataset->GetRasterXSize(),
10049
 *                                       poDataset->GetRasterYSize(),
10050
 *                                       poDataset->GetRasterCount(),
10051
 *                                       nullptr);
10052
 *   for( const char* pszFormat: aosFormats )
10053
 *   {
10054
 *      // Remove optional parameters and just print out the MIME type.
10055
 *      const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
10056
 *      printf("Found format %s\n, aosTokens[0]);
10057
 *   }
10058
 * \endcode
10059
 *
10060
 * @since GDAL 3.7
10061
 */
10062
CPLStringList
10063
GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
10064
                                   CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10065
                                   CPL_UNUSED int nBandCount,
10066
                                   CPL_UNUSED const int *panBandList)
10067
0
{
10068
0
    return CPLStringList();
10069
0
}
10070
10071
/************************************************************************/
10072
/*                 GDALDatasetGetCompressionFormats()                   */
10073
/************************************************************************/
10074
10075
/** Return the compression formats that can be natively obtained for the
10076
 * window of interest and requested bands.
10077
 *
10078
 * For example, a tiled dataset may be able to return data in a compressed
10079
 * format if the window of interest matches exactly a tile. For some formats,
10080
 * drivers may also be able to merge several tiles together (not currently
10081
 * implemented though).
10082
 *
10083
 * Each format string is a pseudo MIME type, whose first part can be passed
10084
 * as the pszFormat argument of ReadCompressedData(), with additional
10085
 * parameters specified as key=value with a semi-colon separator.
10086
 *
10087
 * The amount and types of optional parameters passed after the MIME type is
10088
 * format dependent, and driver dependent (some drivers might not be able to
10089
 * return those extra information without doing a rather costly processing).
10090
 *
10091
 * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
10092
 * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
10093
 * consequently "JPEG" can be passed as the pszFormat argument of
10094
 * ReadCompressedData(). For JPEG, implementations can use the
10095
 * GDALGetCompressionFormatForJPEG() helper method to generate a string like
10096
 * above from a JPEG codestream.
10097
 *
10098
 * Several values might be returned. For example,
10099
 * the JPEGXL driver will return "JXL", but also potentially "JPEG"
10100
 * if the JPEGXL codestream includes a JPEG reconstruction box.
10101
 *
10102
 * In the general case this method will return an empty list.
10103
 *
10104
 * This is the same as C++ method GDALDataset::GetCompressionFormats().
10105
 *
10106
 * @param hDS Dataset handle.
10107
 *
10108
 * @param nXOff The pixel offset to the top left corner of the region
10109
 * of the band to be accessed.  This would be zero to start from the left side.
10110
 *
10111
 * @param nYOff The line offset to the top left corner of the region
10112
 * of the band to be accessed.  This would be zero to start from the top.
10113
 *
10114
 * @param nXSize The width of the region of the band to be accessed in pixels.
10115
 *
10116
 * @param nYSize The height of the region of the band to be accessed in lines.
10117
 *
10118
 * @param nBandCount the number of bands being requested.
10119
 *
10120
 * @param panBandList the list of nBandCount band numbers.
10121
 * Note band numbers are 1 based. This may be NULL to select the first
10122
 * nBandCount bands.
10123
 *
10124
 * @return a list of compatible formats (which may be empty) that should be
10125
 * freed with CSLDestroy(), or nullptr.
10126
 *
10127
 * @since GDAL 3.7
10128
 */
10129
char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
10130
                                        int nXSize, int nYSize, int nBandCount,
10131
                                        const int *panBandList)
10132
0
{
10133
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
10134
0
    return GDALDataset::FromHandle(hDS)
10135
0
        ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
10136
0
                                panBandList)
10137
0
        .StealList();
10138
0
}
10139
10140
/************************************************************************/
10141
/*                         ReadCompressedData()                         */
10142
/************************************************************************/
10143
10144
/** Return the compressed content that can be natively obtained for the
10145
 * window of interest and requested bands.
10146
 *
10147
 * For example, a tiled dataset may be able to return data in compressed format
10148
 * if the window of interest matches exactly a tile. For some formats, drivers
10149
 * may also be example to merge several tiles together (not currently
10150
 * implemented though).
10151
 *
10152
 * The implementation should make sure that the content returned forms a valid
10153
 * standalone file. For example, for the GeoTIFF implementation of this method,
10154
 * when extracting a JPEG tile, the method will automatically add the content
10155
 * of the JPEG Huffman and/or quantization tables that might be stored in the
10156
 * TIFF JpegTables tag, and not in tile data itself.
10157
 *
10158
 * In the general case this method will return CE_Failure.
10159
 *
10160
 * This is the same as C function GDALDatasetReadCompressedData().
10161
 *
10162
 * @param pszFormat Requested compression format (e.g. "JPEG",
10163
 * "WEBP", "JXL"). This is the MIME type of one of the values
10164
 * returned by GetCompressionFormats(). The format string is designed to
10165
 * potentially include at a later point key=value optional parameters separated
10166
 * by a semi-colon character. At time of writing, none are implemented.
10167
 * ReadCompressedData() implementations should verify optional parameters and
10168
 * return CE_Failure if they cannot support one of them.
10169
 *
10170
 * @param nXOff The pixel offset to the top left corner of the region
10171
 * of the band to be accessed.  This would be zero to start from the left side.
10172
 *
10173
 * @param nYOff The line offset to the top left corner of the region
10174
 * of the band to be accessed.  This would be zero to start from the top.
10175
 *
10176
 * @param nXSize The width of the region of the band to be accessed in pixels.
10177
 *
10178
 * @param nYSize The height of the region of the band to be accessed in lines.
10179
 *
10180
 * @param nBandCount the number of bands being requested.
10181
 *
10182
 * @param panBandList the list of nBandCount band numbers.
10183
 * Note band numbers are 1 based. This may be NULL to select the first
10184
 * nBandCount bands.
10185
 *
10186
 * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10187
 * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10188
 * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10189
 * buffer will be filled with the compressed data, provided that pnBufferSize
10190
 * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10191
 * of *ppBuffer, is sufficiently large to hold the data.
10192
 * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10193
 * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10194
 * free it with VSIFree().
10195
 * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10196
 * but *pnBufferSize will be updated with an upper bound of the size that would
10197
 * be necessary to hold it (if pnBufferSize != nullptr).
10198
 *
10199
 * @param pnBufferSize Output buffer size, or nullptr.
10200
 * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10201
 * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10202
 * method is successful, *pnBufferSize will be updated with the actual size
10203
 * used.
10204
 *
10205
 * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10206
 * If ppszDetailedFormat is not nullptr, then, on success, the method will
10207
 * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10208
 * *ppszDetailedFormat might contain strings like
10209
 * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10210
 * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10211
 * The string will contain at least as much information as what
10212
 * GetCompressionFormats() returns, and potentially more when
10213
 * ppBuffer != nullptr.
10214
 *
10215
 * @return CE_None in case of success, CE_Failure otherwise.
10216
 *
10217
 * For example, to request JPEG content on the whole image and let GDAL deal
10218
 * with the buffer allocation.
10219
 * \code{.cpp}
10220
 *   void* pBuffer = nullptr;
10221
 *   size_t nBufferSize = 0;
10222
 *   CPLErr eErr =
10223
 *      poDataset->ReadCompressedData("JPEG",
10224
 *                                    0, 0,
10225
 *                                    poDataset->GetRasterXSize(),
10226
 *                                    poDataset->GetRasterYSize(),
10227
 *                                    poDataset->GetRasterCount(),
10228
 *                                    nullptr, // panBandList
10229
 *                                    &pBuffer,
10230
 *                                    &nBufferSize,
10231
 *                                    nullptr // ppszDetailedFormat
10232
 *                                   );
10233
 *   if (eErr == CE_None)
10234
 *   {
10235
 *       CPLAssert(pBuffer != nullptr);
10236
 *       CPLAssert(nBufferSize > 0);
10237
 *       VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
10238
 *       if (fp)
10239
 *       {
10240
 *           VSIFWriteL(pBuffer, nBufferSize, 1, fp);
10241
 *           VSIFCloseL(fp);
10242
 *       }
10243
 *       VSIFree(pBuffer);
10244
 *   }
10245
 * \endcode
10246
 *
10247
 * Or to manage the buffer allocation on your side:
10248
 * \code{.cpp}
10249
 *   size_t nUpperBoundBufferSize = 0;
10250
 *   CPLErr eErr =
10251
 *      poDataset->ReadCompressedData("JPEG",
10252
 *                                    0, 0,
10253
 *                                    poDataset->GetRasterXSize(),
10254
 *                                    poDataset->GetRasterYSize(),
10255
 *                                    poDataset->GetRasterCount(),
10256
 *                                    nullptr, // panBandList
10257
 *                                    nullptr, // ppBuffer,
10258
 *                                    &nUpperBoundBufferSize,
10259
 *                                    nullptr // ppszDetailedFormat
10260
 *                                   );
10261
 *   if (eErr == CE_None)
10262
 *   {
10263
 *       std::vector<uint8_t> myBuffer;
10264
 *       myBuffer.resize(nUpperBoundBufferSize);
10265
 *       void* pBuffer = myBuffer.data();
10266
 *       size_t nActualSize = nUpperBoundBufferSize;
10267
 *       char* pszDetailedFormat = nullptr;
10268
 *       // We also request detailed format, but we could have passed it to
10269
 *       // nullptr as well.
10270
 *       eErr =
10271
 *         poDataset->ReadCompressedData("JPEG",
10272
 *                                       0, 0,
10273
 *                                       poDataset->GetRasterXSize(),
10274
 *                                       poDataset->GetRasterYSize(),
10275
 *                                       poDataset->GetRasterCount(),
10276
 *                                       nullptr, // panBandList
10277
 *                                       &pBuffer,
10278
 *                                       &nActualSize,
10279
 *                                       &pszDetailedFormat);
10280
 *       if (eErr == CE_None)
10281
 *       {
10282
 *          CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10283
 *          CPLAssert(nActualSize <= nUpperBoundBufferSize);
10284
 *          myBuffer.resize(nActualSize);
10285
 *          // do something useful
10286
 *          VSIFree(pszDetailedFormat);
10287
 *       }
10288
 *   }
10289
 * \endcode
10290
 *
10291
 * @since GDAL 3.7
10292
 */
10293
CPLErr GDALDataset::ReadCompressedData(
10294
    CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10295
    CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10296
    CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10297
    CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10298
    CPL_UNUSED char **ppszDetailedFormat)
10299
0
{
10300
0
    return CE_Failure;
10301
0
}
10302
10303
/************************************************************************/
10304
/*                  GDALDatasetReadCompressedData()                     */
10305
/************************************************************************/
10306
10307
/** Return the compressed content that can be natively obtained for the
10308
 * window of interest and requested bands.
10309
 *
10310
 * For example, a tiled dataset may be able to return data in compressed format
10311
 * if the window of interest matches exactly a tile. For some formats, drivers
10312
 * may also be example to merge several tiles together (not currently
10313
 * implemented though).
10314
 *
10315
 * The implementation should make sure that the content returned forms a valid
10316
 * standalone file. For example, for the GeoTIFF implementation of this method,
10317
 * when extracting a JPEG tile, the method will automatically adds the content
10318
 * of the JPEG Huffman and/or quantization tables that might be stored in the
10319
 * TIFF JpegTables tag, and not in tile data itself.
10320
 *
10321
 * In the general case this method will return CE_Failure.
10322
 *
10323
 * This is the same as C++ method GDALDataset:ReadCompressedData().
10324
 *
10325
 * @param hDS Dataset handle.
10326
 *
10327
 * @param pszFormat Requested compression format (e.g. "JPEG",
10328
 * "WEBP", "JXL"). This is the MIME type of one of the values
10329
 * returned by GetCompressionFormats(). The format string is designed to
10330
 * potentially include at a later point key=value optional parameters separated
10331
 * by a semi-colon character. At time of writing, none are implemented.
10332
 * ReadCompressedData() implementations should verify optional parameters and
10333
 * return CE_Failure if they cannot support one of them.
10334
 *
10335
 * @param nXOff The pixel offset to the top left corner of the region
10336
 * of the band to be accessed.  This would be zero to start from the left side.
10337
 *
10338
 * @param nYOff The line offset to the top left corner of the region
10339
 * of the band to be accessed.  This would be zero to start from the top.
10340
 *
10341
 * @param nXSize The width of the region of the band to be accessed in pixels.
10342
 *
10343
 * @param nYSize The height of the region of the band to be accessed in lines.
10344
 *
10345
 * @param nBandCount the number of bands being requested.
10346
 *
10347
 * @param panBandList the list of nBandCount band numbers.
10348
 * Note band numbers are 1 based. This may be NULL to select the first
10349
 * nBandCount bands.
10350
 *
10351
 * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10352
 * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10353
 * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10354
 * buffer will be filled with the compressed data, provided that pnBufferSize
10355
 * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10356
 * of *ppBuffer, is sufficiently large to hold the data.
10357
 * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10358
 * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10359
 * free it with VSIFree().
10360
 * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10361
 * but *pnBufferSize will be updated with an upper bound of the size that would
10362
 * be necessary to hold it (if pnBufferSize != nullptr).
10363
 *
10364
 * @param pnBufferSize Output buffer size, or nullptr.
10365
 * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10366
 * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10367
 * method is successful, *pnBufferSize will be updated with the actual size
10368
 * used.
10369
 *
10370
 * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10371
 * If ppszDetailedFormat is not nullptr, then, on success, the method will
10372
 * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10373
 * *ppszDetailedFormat might contain strings like
10374
 * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10375
 * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10376
 * The string will contain at least as much information as what
10377
 * GetCompressionFormats() returns, and potentially more when
10378
 * ppBuffer != nullptr.
10379
 *
10380
 * @return CE_None in case of success, CE_Failure otherwise.
10381
 *
10382
 * @since GDAL 3.7
10383
 */
10384
CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10385
                                     int nXOff, int nYOff, int nXSize,
10386
                                     int nYSize, int nBandCount,
10387
                                     const int *panBandList, void **ppBuffer,
10388
                                     size_t *pnBufferSize,
10389
                                     char **ppszDetailedFormat)
10390
0
{
10391
0
    VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10392
0
    return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10393
0
        pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10394
0
        ppBuffer, pnBufferSize, ppszDetailedFormat);
10395
0
}
10396
10397
/************************************************************************/
10398
/*                           CanBeCloned()                              */
10399
/************************************************************************/
10400
10401
//! @cond Doxygen_Suppress
10402
10403
/** This method is called by GDALThreadSafeDataset::Create() to determine if
10404
 * it is possible to create a thread-safe wrapper for a dataset, which involves
10405
 * the ability to Clone() it.
10406
 *
10407
 * Implementations of this method must be thread-safe.
10408
 *
10409
 * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10410
 *                    expressing the intended use for thread-safety.
10411
 *                    Currently, the only valid scope is in the base
10412
 *                    implementation is GDAL_OF_RASTER.
10413
 * @param bCanShareState Determines if cloned datasets are allowed to share
10414
 *                       state with the dataset they have been cloned from.
10415
 *                       If set to true, the dataset from which they have been
10416
 *                       cloned from must remain opened during the lifetime of
10417
 *                       its clones.
10418
 * @return true if the Clone() method is expected to succeed with the same values
10419
 *         of nScopeFlags and bCanShareState.
10420
 */
10421
bool GDALDataset::CanBeCloned(int nScopeFlags,
10422
                              [[maybe_unused]] bool bCanShareState) const
10423
0
{
10424
0
    return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
10425
0
}
10426
10427
//! @endcond
10428
10429
/************************************************************************/
10430
/*                               Clone()                                */
10431
/************************************************************************/
10432
10433
//! @cond Doxygen_Suppress
10434
10435
/** This method "clones" the current dataset, that is it returns a new instance
10436
 * that is opened on the same underlying "file".
10437
 *
10438
 * The base implementation uses GDALDataset::Open() to re-open the dataset.
10439
 * The MEM driver has a specialized implementation that returns a new instance,
10440
 * but which shares the same memory buffer as this.
10441
 *
10442
 * Implementations of this method must be thread-safe.
10443
 *
10444
 * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10445
 *                    expressing the intended use for thread-safety.
10446
 *                    Currently, the only valid scope is in the base
10447
 *                    implementation is GDAL_OF_RASTER.
10448
 * @param bCanShareState Determines if cloned datasets are allowed to share
10449
 *                       state with the dataset they have been cloned from.
10450
 *                       If set to true, the dataset from which they have been
10451
 *                       cloned from must remain opened during the lifetime of
10452
 *                       its clones.
10453
 * @return a new instance, or nullptr in case of error.
10454
 */
10455
std::unique_ptr<GDALDataset>
10456
GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
10457
0
{
10458
0
    CPLStringList aosAllowedDrivers;
10459
0
    if (poDriver)
10460
0
        aosAllowedDrivers.AddString(poDriver->GetDescription());
10461
0
    return std::unique_ptr<GDALDataset>(GDALDataset::Open(
10462
0
        GetDescription(),
10463
0
        nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
10464
0
        aosAllowedDrivers.List(), papszOpenOptions));
10465
0
}
10466
10467
//! @endcond
10468
10469
/************************************************************************/
10470
/*                    GeolocationToPixelLine()                          */
10471
/************************************************************************/
10472
10473
/** Transform georeferenced coordinates to pixel/line coordinates.
10474
 *
10475
 * When poSRS is null, those georeferenced coordinates (dfGeolocX, dfGeolocY)
10476
 * must be in the "natural" SRS of the dataset, that is the one returned by
10477
 * GetSpatialRef() if there is a geotransform, GetGCPSpatialRef() if there are
10478
 * GCPs, WGS 84 if there are RPC coefficients, or the SRS of the geolocation
10479
 * array (generally WGS 84) if there is a geolocation array.
10480
 * If that natural SRS is a geographic one, dfGeolocX must be a longitude, and
10481
 * dfGeolocY a latitude. If that natural SRS is a projected one, dfGeolocX must
10482
 * be a easting, and dfGeolocY a northing.
10483
 *
10484
 * When poSRS is set to a non-null value, (dfGeolocX, dfGeolocY) must be
10485
 * expressed in that CRS, and that tuple must be conformant with the
10486
 * data-axis-to-crs-axis setting of poSRS, that is the one returned by
10487
 * the OGRSpatialReference::GetDataAxisToSRSAxisMapping(). If you want to be sure
10488
 * of the axis order, then make sure to call poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)
10489
 * before calling this method, and in that case, dfGeolocX must be a longitude
10490
 * or an easting value, and dfGeolocX a latitude or a northing value.
10491
 *
10492
 * This method uses GDALCreateGenImgProjTransformer2() underneath.
10493
 *
10494
 * @param dfGeolocX X coordinate of the position (longitude or easting if poSRS
10495
 * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10496
 * where interpolation should be done.
10497
 * @param dfGeolocY Y coordinate of the position (latitude or northing if poSRS
10498
 * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10499
 * where interpolation should be done.
10500
 * @param poSRS If set, override the natural CRS in which dfGeolocX, dfGeolocY are expressed
10501
 * @param[out] pdfPixel Pointer to the variable where to the store the pixel/column coordinate.
10502
 * @param[out] pdfLine Pointer to the variable where to the store the line coordinate.
10503
 * @param papszTransformerOptions Options accepted by GDALCreateGenImgProjTransformer2(), or nullptr.
10504
 *
10505
 * @return CE_None on success, or an error code on failure.
10506
 * @since GDAL 3.11
10507
 */
10508
10509
CPLErr
10510
GDALDataset::GeolocationToPixelLine(double dfGeolocX, double dfGeolocY,
10511
                                    const OGRSpatialReference *poSRS,
10512
                                    double *pdfPixel, double *pdfLine,
10513
                                    CSLConstList papszTransformerOptions) const
10514
0
{
10515
0
    CPLStringList aosTO(papszTransformerOptions);
10516
10517
0
    if (poSRS)
10518
0
    {
10519
0
        const char *const apszOptions[] = {"FORMAT=WKT2", nullptr};
10520
0
        const std::string osWKT = poSRS->exportToWkt(apszOptions);
10521
0
        aosTO.SetNameValue("DST_SRS", osWKT.c_str());
10522
0
        const auto eAxisMappingStrategy = poSRS->GetAxisMappingStrategy();
10523
0
        if (eAxisMappingStrategy == OAMS_TRADITIONAL_GIS_ORDER)
10524
0
            aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10525
0
                               "TRADITIONAL_GIS_ORDER");
10526
0
        else if (eAxisMappingStrategy == OAMS_AUTHORITY_COMPLIANT)
10527
0
            aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10528
0
                               "AUTHORITY_COMPLIANT");
10529
0
        else
10530
0
        {
10531
0
            const auto &anValues = poSRS->GetDataAxisToSRSAxisMapping();
10532
0
            std::string osVal;
10533
0
            for (int v : anValues)
10534
0
            {
10535
0
                if (!osVal.empty())
10536
0
                    osVal += ',';
10537
0
                osVal += std::to_string(v);
10538
0
            }
10539
0
            aosTO.SetNameValue("DST_SRS_DATA_AXIS_TO_SRS_AXIS_MAPPING",
10540
0
                               osVal.c_str());
10541
0
        }
10542
0
    }
10543
10544
0
    auto hTransformer = GDALCreateGenImgProjTransformer2(
10545
0
        GDALDataset::ToHandle(const_cast<GDALDataset *>(this)), nullptr,
10546
0
        aosTO.List());
10547
0
    if (hTransformer == nullptr)
10548
0
    {
10549
0
        return CE_Failure;
10550
0
    }
10551
10552
0
    double z = 0;
10553
0
    int bSuccess = 0;
10554
0
    GDALGenImgProjTransform(hTransformer, TRUE, 1, &dfGeolocX, &dfGeolocY, &z,
10555
0
                            &bSuccess);
10556
0
    GDALDestroyTransformer(hTransformer);
10557
0
    if (bSuccess)
10558
0
    {
10559
0
        if (pdfPixel)
10560
0
            *pdfPixel = dfGeolocX;
10561
0
        if (pdfLine)
10562
0
            *pdfLine = dfGeolocY;
10563
0
        return CE_None;
10564
0
    }
10565
0
    else
10566
0
    {
10567
0
        return CE_Failure;
10568
0
    }
10569
0
}
10570
10571
/************************************************************************/
10572
/*                  GDALDatasetGeolocationToPixelLine()                 */
10573
/************************************************************************/
10574
10575
/** Transform georeferenced coordinates to pixel/line coordinates.
10576
 *
10577
 * @see GDALDataset::GeolocationToPixelLine()
10578
 * @since GDAL 3.11
10579
 */
10580
10581
CPLErr GDALDatasetGeolocationToPixelLine(GDALDatasetH hDS, double dfGeolocX,
10582
                                         double dfGeolocY,
10583
                                         OGRSpatialReferenceH hSRS,
10584
                                         double *pdfPixel, double *pdfLine,
10585
                                         CSLConstList papszTransformerOptions)
10586
0
{
10587
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGeolocationToPixelLine", CE_Failure);
10588
10589
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
10590
0
    return poDS->GeolocationToPixelLine(
10591
0
        dfGeolocX, dfGeolocY, OGRSpatialReference::FromHandle(hSRS), pdfPixel,
10592
0
        pdfLine, papszTransformerOptions);
10593
0
}
10594
10595
/************************************************************************/
10596
/*                               GetExtent()                            */
10597
/************************************************************************/
10598
10599
/** Return extent of dataset in specified CRS.
10600
 *
10601
 * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10602
 *
10603
 * For rasters, the base implementation of this method only succeeds if
10604
 * GetGeoTransform() and GetSpatialRef() succeed.
10605
 * For vectors, the base implementation of this method iterates over layers
10606
 * and call their OGRLayer::GetExtent() method.
10607
 *
10608
 * TestCapability(GDsCFastGetExtent) can be used to test if the execution
10609
 * time of this method is fast.
10610
 *
10611
 * This is the same as C function GDALGetExtent()
10612
 *
10613
 * @param[out] psExtent Pointer to output extent. Must NOT be null.
10614
 * @param poCRS CRS in which to express the extent. If not specified, this will
10615
 * be the raster CRS or the CRS of the first layer for a vector dataset.
10616
 * @return CE_None in case of success, CE_Failure otherwise
10617
 * @since GDAL 3.12
10618
 */
10619
10620
CPLErr GDALDataset::GetExtent(OGREnvelope *psExtent,
10621
                              const OGRSpatialReference *poCRS) const
10622
0
{
10623
0
    auto poThisDS = const_cast<GDALDataset *>(this);
10624
0
    const OGRSpatialReference *poThisCRS = poThisDS->GetSpatialRef();
10625
0
    int nLayerCount = 0;
10626
0
    if (!poThisCRS)
10627
0
    {
10628
0
        nLayerCount = poThisDS->GetLayerCount();
10629
0
        if (nLayerCount >= 1)
10630
0
        {
10631
0
            if (auto poLayer = poThisDS->GetLayer(0))
10632
0
                poThisCRS = poLayer->GetSpatialRef();
10633
0
        }
10634
0
        if (poCRS && !poThisCRS)
10635
0
            return CE_Failure;
10636
0
    }
10637
0
    if (!poCRS)
10638
0
        poCRS = poThisCRS;
10639
10640
0
    *psExtent = OGREnvelope();
10641
10642
0
    GDALGeoTransform gt;
10643
0
    const bool bHasGT = poThisDS->GetGeoTransform(gt) == CE_None;
10644
0
    if (bHasGT)
10645
0
    {
10646
0
        std::unique_ptr<OGRCoordinateTransformation> poCT;
10647
0
        if (poCRS)
10648
0
        {
10649
0
            poCT.reset(OGRCreateCoordinateTransformation(poThisCRS, poCRS));
10650
0
        }
10651
10652
0
        constexpr int DENSIFY_POINT_COUNT = 21;
10653
0
        double dfULX = gt[0];
10654
0
        double dfULY = gt[3];
10655
0
        double dfURX = 0, dfURY = 0;
10656
0
        gt.Apply(nRasterXSize, 0, &dfURX, &dfURY);
10657
0
        double dfLLX = 0, dfLLY = 0;
10658
0
        gt.Apply(0, nRasterYSize, &dfLLX, &dfLLY);
10659
0
        double dfLRX = 0, dfLRY = 0;
10660
0
        gt.Apply(nRasterXSize, nRasterYSize, &dfLRX, &dfLRY);
10661
0
        const double xmin = std::min({dfULX, dfURX, dfLLX, dfLRX});
10662
0
        const double ymin = std::min({dfULY, dfURY, dfLLY, dfLRY});
10663
0
        const double xmax = std::max({dfULX, dfURX, dfLLX, dfLRX});
10664
0
        const double ymax = std::max({dfULY, dfURY, dfLLY, dfLRY});
10665
0
        if (poCT)
10666
0
        {
10667
0
            OGREnvelope sEnvTmp;
10668
0
            if (!poCT->TransformBounds(xmin, ymin, xmax, ymax, &(sEnvTmp.MinX),
10669
0
                                       &(sEnvTmp.MinY), &(sEnvTmp.MaxX),
10670
0
                                       &(sEnvTmp.MaxY), DENSIFY_POINT_COUNT))
10671
0
            {
10672
0
                return CE_Failure;
10673
0
            }
10674
0
            *psExtent = sEnvTmp;
10675
0
        }
10676
0
        else
10677
0
        {
10678
0
            psExtent->MinX = xmin;
10679
0
            psExtent->MinY = ymin;
10680
0
            psExtent->MaxX = xmax;
10681
0
            psExtent->MaxY = ymax;
10682
0
        }
10683
0
    }
10684
10685
0
    if (nLayerCount > 0)
10686
0
    {
10687
0
        for (auto &&poLayer : poThisDS->GetLayers())
10688
0
        {
10689
0
            auto poLayerCRS = poLayer->GetSpatialRef();
10690
0
            if (poLayerCRS)
10691
0
            {
10692
0
                OGREnvelope sLayerExtent;
10693
0
                if (poLayer->GetExtent(&sLayerExtent) == OGRERR_NONE)
10694
0
                {
10695
0
                    auto poCT = std::unique_ptr<OGRCoordinateTransformation>(
10696
0
                        OGRCreateCoordinateTransformation(poLayerCRS, poCRS));
10697
0
                    if (poCT)
10698
0
                    {
10699
0
                        constexpr int DENSIFY_POINT_COUNT = 21;
10700
0
                        OGREnvelope sEnvTmp;
10701
0
                        if (poCT->TransformBounds(
10702
0
                                sLayerExtent.MinX, sLayerExtent.MinY,
10703
0
                                sLayerExtent.MaxX, sLayerExtent.MaxY,
10704
0
                                &(sEnvTmp.MinX), &(sEnvTmp.MinY),
10705
0
                                &(sEnvTmp.MaxX), &(sEnvTmp.MaxY),
10706
0
                                DENSIFY_POINT_COUNT))
10707
0
                        {
10708
0
                            psExtent->Merge(sEnvTmp);
10709
0
                        }
10710
0
                    }
10711
0
                }
10712
0
            }
10713
0
        }
10714
0
    }
10715
10716
0
    return psExtent->IsInit() ? CE_None : CE_Failure;
10717
0
}
10718
10719
/************************************************************************/
10720
/*                           GDALGetExtent()                            */
10721
/************************************************************************/
10722
10723
/** Return extent of dataset in specified CRS.
10724
 *
10725
 * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10726
 *
10727
 * For rasters, the base implementation of this method only succeeds if
10728
 * GetGeoTransform() and GetSpatialRef() succeed.
10729
 * For vectors, the base implementation of this method iterates over layers
10730
 * and call their OGRLayer::GetExtent() method.
10731
 *
10732
 * TestCapability(GDsCFastGetExtent) can be used to test if the execution
10733
 * time of this method is fast.
10734
 *
10735
 * This is the same as C++ method GDALDataset::GetExtent()
10736
 *
10737
 * @param hDS Dataset handle. Must NOT be null.
10738
 * @param[out] psExtent Pointer to output extent. Must NOT be null.
10739
 * @param hCRS CRS in which to express the extent. If not specified, this will
10740
 * be the raster CRS or the CRS of the first layer for a vector dataset.
10741
 * @return extent in poCRS (valid only if IsInit() method returns true)
10742
 * @since GDAL 3.12
10743
 */
10744
10745
CPLErr GDALGetExtent(GDALDatasetH hDS, OGREnvelope *psExtent,
10746
                     OGRSpatialReferenceH hCRS)
10747
0
{
10748
0
    VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10749
0
    VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
10750
0
    return GDALDataset::FromHandle(hDS)->GetExtent(
10751
0
        psExtent, OGRSpatialReference::FromHandle(hCRS));
10752
0
}
10753
10754
/************************************************************************/
10755
/*                         GetExtentWGS84LongLat()                      */
10756
/************************************************************************/
10757
10758
/** Return extent of dataset in WGS84 longitude/latitude
10759
 *
10760
 * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10761
 *
10762
 * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
10763
 * time of this method is fast.
10764
 *
10765
 * This is the same as C function GDALGetExtentWGS84LongLat()
10766
 *
10767
 * @return extent (valid only if IsInit() method returns true)
10768
 * @since GDAL 3.12
10769
 */
10770
10771
CPLErr GDALDataset::GetExtentWGS84LongLat(OGREnvelope *psExtent) const
10772
0
{
10773
0
    OGRSpatialReference oSRS_WGS84;
10774
0
    oSRS_WGS84.SetFromUserInput("WGS84");
10775
0
    oSRS_WGS84.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
10776
0
    return GetExtent(psExtent, &oSRS_WGS84);
10777
0
}
10778
10779
/************************************************************************/
10780
/*                    GDALGetExtentWGS84LongLat()                       */
10781
/************************************************************************/
10782
10783
/** Return extent of dataset in WGS84 longitude/latitude
10784
 *
10785
 * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10786
 *
10787
 * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
10788
 * time of this method is fast.
10789
 *
10790
 * This is the same as C++ method GDALDataset::GetExtentWGS84LongLat()
10791
 *
10792
 * @param hDS Dataset handle. Must NOT be null.
10793
 * @param[out] psExtent Pointer to output extent. Must NOT be null.
10794
 * @return extent (valid only if IsInit() method returns true)
10795
 * @since GDAL 3.12
10796
 */
10797
10798
CPLErr GDALGetExtentWGS84LongLat(GDALDatasetH hDS, OGREnvelope *psExtent)
10799
0
{
10800
0
    VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10801
0
    VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
10802
0
    return GDALDataset::FromHandle(hDS)->GetExtentWGS84LongLat(psExtent);
10803
0
}
10804
10805
/************************************************************************/
10806
/*                  ReportUpdateNotSupportedByDriver()                  */
10807
/************************************************************************/
10808
10809
//! @cond Doxygen_Suppress
10810
10811
/* static */
10812
void GDALDataset::ReportUpdateNotSupportedByDriver(const char *pszDriverName)
10813
0
{
10814
0
    CPLError(CE_Failure, CPLE_NotSupported,
10815
0
             "The %s driver does not support update access to existing "
10816
0
             "datasets.",
10817
0
             pszDriverName);
10818
0
}
10819
10820
//! @endcond
10821
10822
/************************************************************************/
10823
/*                         BuildFilename()                              */
10824
/************************************************************************/
10825
10826
/** Generates a filename, potentially relative to another one.
10827
 *
10828
 * Given the path to a reference directory, and a path to a file
10829
 * referenced from it, build a path to the file that the current application
10830
 * can use. If the file path is already absolute, rather than relative, or if
10831
 * bRelativeToReferencePath is false, then the filename of interest will be
10832
 * returned unaltered.
10833
 *
10834
 * This is enhanced version of CPLProjectRelativeFilenameSafe() that takes
10835
 * into account the subdataset syntax.
10836
 *
10837
 * Examples:
10838
 * \code{.cpp}
10839
 * BuildFilename("tmp/abc.gif", "abc/def", true) == "abc/def/tmp/abc.gif"
10840
 * BuildFilename("../abc.gif", "/abc/def") == "/abc/abc.gif"
10841
 * BuildFilename("abc.gif", "C:\WIN", true) == "C:\WIN\abc.gif"
10842
 * BuildFilename("abc.gif", "C:\WIN", false) == "abc.gif"
10843
 * BuildFilename("/home/even/foo.tif", "/home/even/workdir", true) == "/home/even/foo.tif"
10844
 * \endcode
10845
 *
10846
 * @param pszFilename Filename of interest.
10847
 * @param pszReferencePath Path to a reference directory.
10848
 * @param bRelativeToReferencePath Whether pszFilename, if a relative path, is
10849
 *                                 relative to pszReferencePath
10850
 * @since 3.11
10851
 */
10852
10853
/* static */
10854
std::string GDALDataset::BuildFilename(const char *pszFilename,
10855
                                       const char *pszReferencePath,
10856
                                       bool bRelativeToReferencePath)
10857
0
{
10858
0
    std::string osSrcDSName;
10859
0
    if (pszReferencePath != nullptr && bRelativeToReferencePath)
10860
0
    {
10861
        // Try subdatasetinfo API first
10862
        // Note: this will become the only branch when subdatasetinfo will become
10863
        //       available for NITF_IM, RASTERLITE and TILEDB
10864
0
        const auto oSubDSInfo{GDALGetSubdatasetInfo(pszFilename)};
10865
0
        if (oSubDSInfo && !oSubDSInfo->GetPathComponent().empty())
10866
0
        {
10867
0
            auto path{oSubDSInfo->GetPathComponent()};
10868
0
            osSrcDSName = oSubDSInfo->ModifyPathComponent(
10869
0
                CPLProjectRelativeFilenameSafe(pszReferencePath, path.c_str())
10870
0
                    .c_str());
10871
0
            GDALDestroySubdatasetInfo(oSubDSInfo);
10872
0
        }
10873
0
        else
10874
0
        {
10875
0
            bool bDone = false;
10876
0
            for (const char *pszSyntax : apszSpecialSubDatasetSyntax)
10877
0
            {
10878
0
                CPLString osPrefix(pszSyntax);
10879
0
                osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
10880
0
                if (pszSyntax[osPrefix.size()] == '"')
10881
0
                    osPrefix += '"';
10882
0
                if (EQUALN(pszFilename, osPrefix, osPrefix.size()))
10883
0
                {
10884
0
                    if (STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}"))
10885
0
                    {
10886
0
                        const char *pszLastPart = strrchr(pszFilename, ':') + 1;
10887
                        // CSV:z:/foo.xyz
10888
0
                        if ((pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
10889
0
                            pszLastPart - pszFilename >= 3 &&
10890
0
                            pszLastPart[-3] == ':')
10891
0
                        {
10892
0
                            pszLastPart -= 2;
10893
0
                        }
10894
0
                        CPLString osPrefixFilename = pszFilename;
10895
0
                        osPrefixFilename.resize(pszLastPart - pszFilename);
10896
0
                        osSrcDSName = osPrefixFilename +
10897
0
                                      CPLProjectRelativeFilenameSafe(
10898
0
                                          pszReferencePath, pszLastPart);
10899
0
                        bDone = true;
10900
0
                    }
10901
0
                    else if (STARTS_WITH_CI(pszSyntax + osPrefix.size(),
10902
0
                                            "{FILENAME}"))
10903
0
                    {
10904
0
                        CPLString osFilename(pszFilename + osPrefix.size());
10905
0
                        size_t nPos = 0;
10906
0
                        if (osFilename.size() >= 3 && osFilename[1] == ':' &&
10907
0
                            (osFilename[2] == '\\' || osFilename[2] == '/'))
10908
0
                            nPos = 2;
10909
0
                        nPos = osFilename.find(
10910
0
                            pszSyntax[osPrefix.size() + strlen("{FILENAME}")],
10911
0
                            nPos);
10912
0
                        if (nPos != std::string::npos)
10913
0
                        {
10914
0
                            const CPLString osSuffix = osFilename.substr(nPos);
10915
0
                            osFilename.resize(nPos);
10916
0
                            osSrcDSName = osPrefix +
10917
0
                                          CPLProjectRelativeFilenameSafe(
10918
0
                                              pszReferencePath, osFilename) +
10919
0
                                          osSuffix;
10920
0
                            bDone = true;
10921
0
                        }
10922
0
                    }
10923
0
                    break;
10924
0
                }
10925
0
            }
10926
0
            if (!bDone)
10927
0
            {
10928
0
                std::string osReferencePath = pszReferencePath;
10929
0
                if (!CPLIsFilenameRelative(pszReferencePath))
10930
0
                {
10931
                    // Simplify path by replacing "foo/a/../b" with "foo/b"
10932
0
                    while (STARTS_WITH(pszFilename, "../"))
10933
0
                    {
10934
0
                        osReferencePath =
10935
0
                            CPLGetPathSafe(osReferencePath.c_str());
10936
0
                        pszFilename += strlen("../");
10937
0
                    }
10938
0
                }
10939
10940
0
                osSrcDSName = CPLProjectRelativeFilenameSafe(
10941
0
                    osReferencePath.c_str(), pszFilename);
10942
0
            }
10943
0
        }
10944
0
    }
10945
0
    else
10946
0
    {
10947
0
        osSrcDSName = pszFilename;
10948
0
    }
10949
0
    return osSrcDSName;
10950
0
}