Coverage Report

Created: 2025-06-13 06:29

/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 <climits>
19
#include <cstdarg>
20
#include <cstdio>
21
#include <cstdlib>
22
#include <cstring>
23
#include <algorithm>
24
#include <map>
25
#include <mutex>
26
#include <new>
27
#include <set>
28
#include <string>
29
#include <utility>
30
31
#include "cpl_conv.h"
32
#include "cpl_error.h"
33
#include "cpl_hash_set.h"
34
#include "cpl_multiproc.h"
35
#include "cpl_progress.h"
36
#include "cpl_string.h"
37
#include "cpl_vsi.h"
38
#include "cpl_vsi_error.h"
39
#include "gdal_alg.h"
40
#include "ogr_api.h"
41
#include "ogr_attrind.h"
42
#include "ogr_core.h"
43
#include "ogr_feature.h"
44
#include "ogr_featurestyle.h"
45
#include "ogr_gensql.h"
46
#include "ogr_geometry.h"
47
#include "ogr_p.h"
48
#include "ogr_spatialref.h"
49
#include "ogr_srs_api.h"
50
#include "ograpispy.h"
51
#include "ogrsf_frmts.h"
52
#include "ogrunionlayer.h"
53
#include "ogr_swq.h"
54
55
#include "../frmts/derived/derivedlist.h"
56
57
#ifdef SQLITE_ENABLED
58
#include "../sqlite/ogrsqliteexecutesql.h"
59
#endif
60
61
extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
62
63
CPL_C_START
64
GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
65
                                           int nYOff, int nXSize, int nYSize,
66
                                           void *pBuf, int nBufXSize,
67
                                           int nBufYSize, GDALDataType eBufType,
68
                                           int nBandCount, int *panBandMap,
69
                                           int nPixelSpace, int nLineSpace,
70
                                           int nBandSpace, char **papszOptions);
71
CPL_C_END
72
73
enum class GDALAllowReadWriteMutexState
74
{
75
    RW_MUTEX_STATE_UNKNOWN,
76
    RW_MUTEX_STATE_ALLOWED,
77
    RW_MUTEX_STATE_DISABLED
78
};
79
80
const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
81
const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
82
83
class GDALDataset::Private
84
{
85
    CPL_DISALLOW_COPY_ASSIGN(Private)
86
87
  public:
88
    CPLMutex *hMutex = nullptr;
89
    std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
90
#ifdef DEBUG_EXTRA
91
    std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
92
#endif
93
    GDALAllowReadWriteMutexState eStateReadWriteMutex =
94
        GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
95
    int nCurrentLayerIdx = 0;
96
    int nLayerCount = -1;
97
    GIntBig nFeatureReadInLayer = 0;
98
    GIntBig nFeatureReadInDataset = 0;
99
    GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
100
    GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
101
    OGRLayer *poCurrentLayer = nullptr;
102
103
    std::mutex m_oMutexWKT{};
104
105
    char *m_pszWKTCached = nullptr;
106
    OGRSpatialReference *m_poSRSCached = nullptr;
107
    char *m_pszWKTGCPCached = nullptr;
108
    OGRSpatialReference *m_poSRSGCPCached = nullptr;
109
110
    GDALDataset *poParentDataset = nullptr;
111
112
    bool m_bOverviewsEnabled = true;
113
114
    std::vector<int>
115
        m_anBandMap{};  // used by RasterIO(). Values are 1, 2, etc.
116
117
0
    Private() = default;
118
};
119
120
struct SharedDatasetCtxt
121
{
122
    // PID of the thread that mark the dataset as shared
123
    // This may not be the actual PID, but the responsiblePID.
124
    GIntBig nPID;
125
    char *pszDescription;
126
    char *pszConcatenatedOpenOptions;
127
    int nOpenFlags;
128
129
    GDALDataset *poDS;
130
};
131
132
// Set of datasets opened as shared datasets (with GDALOpenShared)
133
// The values in the set are of type SharedDatasetCtxt.
134
static CPLHashSet *phSharedDatasetSet = nullptr;
135
136
// Set of all datasets created in the constructor of GDALDataset.
137
// In the case of a shared dataset, memorize the PID of the thread
138
// that marked the dataset as shared, so that we can remove it from
139
// the phSharedDatasetSet in the destructor of the dataset, even
140
// if GDALClose is called from a different thread.
141
static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
142
143
static CPLMutex *hDLMutex = nullptr;
144
145
// Static array of all datasets. Used by GDALGetOpenDatasets.
146
// Not thread-safe. See GDALGetOpenDatasets.
147
static GDALDataset **ppDatasets = nullptr;
148
149
static unsigned long GDALSharedDatasetHashFunc(const void *elt)
150
0
{
151
0
    const SharedDatasetCtxt *psStruct =
152
0
        static_cast<const SharedDatasetCtxt *>(elt);
153
0
    return static_cast<unsigned long>(
154
0
        CPLHashSetHashStr(psStruct->pszDescription) ^
155
0
        CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
156
0
        psStruct->nOpenFlags ^ psStruct->nPID);
157
0
}
158
159
static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
160
0
{
161
0
    const SharedDatasetCtxt *psStruct1 =
162
0
        static_cast<const SharedDatasetCtxt *>(elt1);
163
0
    const SharedDatasetCtxt *psStruct2 =
164
0
        static_cast<const SharedDatasetCtxt *>(elt2);
165
0
    return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
166
0
           strcmp(psStruct1->pszConcatenatedOpenOptions,
167
0
                  psStruct2->pszConcatenatedOpenOptions) == 0 &&
168
0
           psStruct1->nPID == psStruct2->nPID &&
169
0
           psStruct1->nOpenFlags == psStruct2->nOpenFlags;
170
0
}
171
172
static void GDALSharedDatasetFreeFunc(void *elt)
173
0
{
174
0
    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
175
0
    CPLFree(psStruct->pszDescription);
176
0
    CPLFree(psStruct->pszConcatenatedOpenOptions);
177
0
    CPLFree(psStruct);
178
0
}
179
180
static std::string
181
GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
182
0
{
183
0
    std::string osStr;
184
0
    for (const char *pszOption : cpl::Iterate(papszOpenOptions))
185
0
        osStr += pszOption;
186
0
    return osStr;
187
0
}
188
189
/************************************************************************/
190
/* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
191
/************************************************************************/
192
193
// The open-shared mutex must be used by the ProxyPool too.
194
CPLMutex **GDALGetphDLMutex()
195
0
{
196
0
    return &hDLMutex;
197
0
}
198
199
// The current thread will act in the behalf of the thread of PID
200
// responsiblePID.
201
void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
202
0
{
203
0
    GIntBig *pResponsiblePID =
204
0
        static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
205
0
    if (pResponsiblePID == nullptr)
206
0
    {
207
0
        pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
208
0
        CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
209
0
    }
210
0
    *pResponsiblePID = responsiblePID;
211
0
}
212
213
// Get the PID of the thread that the current thread will act in the behalf of
214
// By default : the current thread acts in the behalf of itself.
215
GIntBig GDALGetResponsiblePIDForCurrentThread()
216
0
{
217
0
    GIntBig *pResponsiblePID =
218
0
        static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
219
0
    if (pResponsiblePID == nullptr)
220
0
        return CPLGetPID();
221
0
    return *pResponsiblePID;
222
0
}
223
224
/************************************************************************/
225
/* ==================================================================== */
226
/*                             GDALDataset                              */
227
/* ==================================================================== */
228
/************************************************************************/
229
230
/**
231
 * \class GDALDataset "gdal_priv.h"
232
 *
233
 * A dataset encapsulating one or more raster bands.  Details are further
234
 * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
235
 * Raster Data Model</a>.
236
 *
237
 * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
238
 * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
239
 * dataset.
240
 */
241
242
/************************************************************************/
243
/*                            GDALDataset()                             */
244
/************************************************************************/
245
246
//! @cond Doxygen_Suppress
247
GDALDataset::GDALDataset()
248
0
    : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
249
0
{
250
0
}
251
252
GDALDataset::GDALDataset(int bForceCachedIOIn)
253
0
    : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
254
0
      m_poPrivate(new(std::nothrow) GDALDataset::Private)
255
0
{
256
0
}
257
258
//! @endcond
259
260
/************************************************************************/
261
/*                            ~GDALDataset()                            */
262
/************************************************************************/
263
264
/**
265
 * \brief Destroy an open GDALDataset.
266
 *
267
 * This is the accepted method of closing a GDAL dataset and deallocating
268
 * all resources associated with it.
269
 *
270
 * Equivalent of the C callable GDALClose().  Except that GDALClose() first
271
 * decrements the reference count, and then closes only if it has dropped to
272
 * zero.
273
 *
274
 * For Windows users, it is not recommended to use the delete operator on the
275
 * dataset object because of known issues when allocating and freeing memory
276
 * across module boundaries. Calling GDALClose() is then a better option.
277
 */
278
279
GDALDataset::~GDALDataset()
280
281
0
{
282
    // we don't want to report destruction of datasets that
283
    // were never really open or meant as internal
284
0
    if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
285
0
    {
286
0
        if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
287
0
            CPLDebug("GDAL",
288
0
                     "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
289
0
                     GetDescription(), this, static_cast<int>(CPLGetPID()),
290
0
                     static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
291
0
        else
292
0
            CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
293
0
    }
294
295
0
    if (IsMarkedSuppressOnClose())
296
0
    {
297
0
        if (poDriver == nullptr ||
298
            // Someone issuing Create("foo.tif") on a
299
            // memory driver doesn't expect files with those names to be deleted
300
            // on a file system...
301
            // This is somewhat messy. Ideally there should be a way for the
302
            // driver to overload the default behavior
303
0
            (!EQUAL(poDriver->GetDescription(), "MEM") &&
304
0
             !EQUAL(poDriver->GetDescription(), "Memory")))
305
0
        {
306
0
            VSIUnlink(GetDescription());
307
0
        }
308
0
    }
309
310
    /* -------------------------------------------------------------------- */
311
    /*      Remove dataset from the "open" dataset list.                    */
312
    /* -------------------------------------------------------------------- */
313
0
    if (!bIsInternal)
314
0
    {
315
0
        CPLMutexHolderD(&hDLMutex);
316
0
        if (poAllDatasetMap)
317
0
        {
318
0
            std::map<GDALDataset *, GIntBig>::iterator oIter =
319
0
                poAllDatasetMap->find(this);
320
0
            CPLAssert(oIter != poAllDatasetMap->end());
321
322
0
            UnregisterFromSharedDataset();
323
324
0
            poAllDatasetMap->erase(oIter);
325
326
0
            if (poAllDatasetMap->empty())
327
0
            {
328
0
                delete poAllDatasetMap;
329
0
                poAllDatasetMap = nullptr;
330
0
                if (phSharedDatasetSet)
331
0
                {
332
0
                    CPLHashSetDestroy(phSharedDatasetSet);
333
0
                }
334
0
                phSharedDatasetSet = nullptr;
335
0
                CPLFree(ppDatasets);
336
0
                ppDatasets = nullptr;
337
0
            }
338
0
        }
339
0
    }
340
341
    /* -------------------------------------------------------------------- */
342
    /*      Destroy the raster bands if they exist.                         */
343
    /* -------------------------------------------------------------------- */
344
0
    for (int i = 0; i < nBands && papoBands != nullptr; ++i)
345
0
    {
346
0
        if (papoBands[i] != nullptr)
347
0
            delete papoBands[i];
348
0
        papoBands[i] = nullptr;
349
0
    }
350
351
0
    CPLFree(papoBands);
352
353
0
    if (m_poStyleTable)
354
0
    {
355
0
        delete m_poStyleTable;
356
0
        m_poStyleTable = nullptr;
357
0
    }
358
359
0
    if (m_poPrivate != nullptr)
360
0
    {
361
0
        if (m_poPrivate->hMutex != nullptr)
362
0
            CPLDestroyMutex(m_poPrivate->hMutex);
363
364
0
#if defined(__COVERITY__) || defined(DEBUG)
365
        // Not needed since at destruction there is no risk of concurrent use.
366
0
        std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
367
0
#endif
368
0
        CPLFree(m_poPrivate->m_pszWKTCached);
369
0
        if (m_poPrivate->m_poSRSCached)
370
0
        {
371
0
            m_poPrivate->m_poSRSCached->Release();
372
0
        }
373
0
        CPLFree(m_poPrivate->m_pszWKTGCPCached);
374
0
        if (m_poPrivate->m_poSRSGCPCached)
375
0
        {
376
0
            m_poPrivate->m_poSRSGCPCached->Release();
377
0
        }
378
0
    }
379
380
0
    delete m_poPrivate;
381
382
0
    CSLDestroy(papszOpenOptions);
383
0
}
384
385
/************************************************************************/
386
/*                             Close()                                  */
387
/************************************************************************/
388
389
/** Do final cleanup before a dataset is destroyed.
390
 *
391
 * This method is typically called by GDALClose() or the destructor of a
392
 * GDALDataset subclass. It might also be called by C++ users before
393
 * destroying a dataset. It should not be called on a shared dataset whose
394
 * reference count is greater than one.
395
 *
396
 * It gives a last chance to the closing process to return an error code if
397
 * something goes wrong, in particular in creation / update scenarios where
398
 * file write or network communication might occur when finalizing the dataset.
399
 *
400
 * Implementations should be robust to this method to be called several times
401
 * (on subsequent calls, it should do nothing and return CE_None).
402
 * Once it has been called, no other method than Close() or the dataset
403
 * destructor should be called. RasterBand or OGRLayer owned by the dataset
404
 * should be assumed as no longer being valid.
405
 *
406
 * If a driver implements this method, it must also call it from its
407
 * dataset destructor.
408
 *
409
 * A typical implementation might look as the following
410
 * \code{.cpp}
411
 *
412
 *  MyDataset::~MyDataset()
413
 *  {
414
 *     try
415
 *     {
416
 *         MyDataset::Close();
417
 *     }
418
 *     catch (const std::exception &exc)
419
 *     {
420
 *         // If Close() can throw exception
421
 *         CPLError(CE_Failure, CPLE_AppDefined,
422
 *                  "Exception thrown in MyDataset::Close(): %s",
423
 *                  exc.what());
424
 *     }
425
 *     catch (...)
426
 *     {
427
 *         // If Close() can throw exception
428
 *         CPLError(CE_Failure, CPLE_AppDefined,
429
 *                  "Exception thrown in MyDataset::Close()");
430
 *     }
431
 *  }
432
 *
433
 *  CPLErr MyDataset::Close()
434
 *  {
435
 *      CPLErr eErr = CE_None;
436
 *      if( nOpenFlags != OPEN_FLAGS_CLOSED )
437
 *      {
438
 *          if( MyDataset::FlushCache(true) != CE_None )
439
 *              eErr = CE_Failure;
440
 *
441
 *          // Do something driver specific
442
 *          if (m_fpImage)
443
 *          {
444
 *              if( VSIFCloseL(m_fpImage) != 0 )
445
 *              {
446
 *                  CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
447
 *                  eErr = CE_Failure;
448
 *              }
449
 *          }
450
 *
451
 *          // Call parent Close() implementation.
452
 *          if( MyParentDatasetClass::Close() != CE_None )
453
 *              eErr = CE_Failure;
454
 *      }
455
 *      return eErr;
456
 *  }
457
 * \endcode
458
 *
459
 * @since GDAL 3.7
460
 */
461
CPLErr GDALDataset::Close()
462
0
{
463
    // Call UnregisterFromSharedDataset() before altering nOpenFlags
464
0
    UnregisterFromSharedDataset();
465
466
0
    nOpenFlags = OPEN_FLAGS_CLOSED;
467
0
    return CE_None;
468
0
}
469
470
/************************************************************************/
471
/*                UnregisterFromSharedDataset()                         */
472
/************************************************************************/
473
474
void GDALDataset::UnregisterFromSharedDataset()
475
0
{
476
0
    if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
477
0
        return;
478
479
0
    CPLMutexHolderD(&hDLMutex);
480
481
0
    std::map<GDALDataset *, GIntBig>::iterator oIter =
482
0
        poAllDatasetMap->find(this);
483
0
    CPLAssert(oIter != poAllDatasetMap->end());
484
0
    const GIntBig nPIDCreatorForShared = oIter->second;
485
0
    bShared = false;
486
0
    SharedDatasetCtxt sStruct;
487
0
    sStruct.nPID = nPIDCreatorForShared;
488
0
    sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
489
0
    sStruct.pszDescription = const_cast<char *>(GetDescription());
490
0
    std::string osConcatenatedOpenOptions =
491
0
        GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
492
0
    sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
493
0
    sStruct.poDS = nullptr;
494
0
    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
495
0
        CPLHashSetLookup(phSharedDatasetSet, &sStruct));
496
0
    if (psStruct && psStruct->poDS == this)
497
0
    {
498
0
        CPLHashSetRemove(phSharedDatasetSet, psStruct);
499
0
    }
500
0
    else
501
0
    {
502
0
        CPLDebug("GDAL",
503
0
                 "Should not happen. Cannot find %s, "
504
0
                 "this=%p in phSharedDatasetSet",
505
0
                 GetDescription(), this);
506
0
    }
507
0
}
508
509
/************************************************************************/
510
/*                      AddToDatasetOpenList()                          */
511
/************************************************************************/
512
513
void GDALDataset::AddToDatasetOpenList()
514
0
{
515
    /* -------------------------------------------------------------------- */
516
    /*      Add this dataset to the open dataset list.                      */
517
    /* -------------------------------------------------------------------- */
518
0
    bIsInternal = false;
519
520
0
    CPLMutexHolderD(&hDLMutex);
521
522
0
    if (poAllDatasetMap == nullptr)
523
0
        poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
524
0
    (*poAllDatasetMap)[this] = -1;
525
0
}
526
527
/************************************************************************/
528
/*                             FlushCache()                             */
529
/************************************************************************/
530
531
/**
532
 * \brief Flush all write cached data to disk.
533
 *
534
 * Any raster (or other GDAL) data written via GDAL calls, but buffered
535
 * internally will be written to disk.
536
 *
537
 * The default implementation of this method just calls the FlushCache() method
538
 * on each of the raster bands and the SyncToDisk() method
539
 * on each of the layers.  Conceptually, calling FlushCache() on a dataset
540
 * should include any work that might be accomplished by calling SyncToDisk()
541
 * on layers in that dataset.
542
 *
543
 * Using this method does not prevent use from calling GDALClose()
544
 * to properly close a dataset and ensure that important data not addressed
545
 * by FlushCache() is written in the file.
546
 *
547
 * This method is the same as the C function GDALFlushCache().
548
 *
549
 * @param bAtClosing Whether this is called from a GDALDataset destructor
550
 * @return CE_None in case of success (note: return value added in GDAL 3.7)
551
 */
552
553
CPLErr GDALDataset::FlushCache(bool bAtClosing)
554
555
0
{
556
0
    CPLErr eErr = CE_None;
557
    // This sometimes happens if a dataset is destroyed before completely
558
    // built.
559
560
0
    if (papoBands)
561
0
    {
562
0
        for (int i = 0; i < nBands; ++i)
563
0
        {
564
0
            if (papoBands[i])
565
0
            {
566
0
                if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
567
0
                    eErr = CE_Failure;
568
0
            }
569
0
        }
570
0
    }
571
572
0
    const int nLayers = GetLayerCount();
573
    // cppcheck-suppress knownConditionTrueFalse
574
0
    if (nLayers > 0)
575
0
    {
576
0
        CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
577
0
        for (int i = 0; i < nLayers; ++i)
578
0
        {
579
0
            OGRLayer *poLayer = GetLayer(i);
580
581
0
            if (poLayer)
582
0
            {
583
0
                if (poLayer->SyncToDisk() != OGRERR_NONE)
584
0
                    eErr = CE_Failure;
585
0
            }
586
0
        }
587
0
    }
588
589
0
    return eErr;
590
0
}
591
592
/************************************************************************/
593
/*                           GDALFlushCache()                           */
594
/************************************************************************/
595
596
/**
597
 * \brief Flush all write cached data to disk.
598
 *
599
 * @see GDALDataset::FlushCache().
600
 * @return CE_None in case of success (note: return value added in GDAL 3.7)
601
 */
602
603
CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
604
605
0
{
606
0
    VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
607
608
0
    return GDALDataset::FromHandle(hDS)->FlushCache(false);
609
0
}
610
611
/************************************************************************/
612
/*                             DropCache()                              */
613
/************************************************************************/
614
615
/**
616
* \brief Drop all write cached data
617
*
618
* This method is the same as the C function GDALDropCache().
619
*
620
* @return CE_None in case of success
621
* @since 3.9
622
*/
623
624
CPLErr GDALDataset::DropCache()
625
626
0
{
627
0
    CPLErr eErr = CE_None;
628
629
0
    if (papoBands)
630
0
    {
631
0
        for (int i = 0; i < nBands; ++i)
632
0
        {
633
0
            if (papoBands[i])
634
0
            {
635
0
                if (papoBands[i]->DropCache() != CE_None)
636
0
                    eErr = CE_Failure;
637
0
            }
638
0
        }
639
0
    }
640
641
0
    return eErr;
642
0
}
643
644
/************************************************************************/
645
/*                           GDALDropCache()                           */
646
/************************************************************************/
647
648
/**
649
* \brief Drop all write cached data
650
*
651
* @see GDALDataset::DropCache().
652
* @return CE_None in case of success
653
* @since 3.9
654
*/
655
656
CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
657
658
0
{
659
0
    VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
660
661
0
    return GDALDataset::FromHandle(hDS)->DropCache();
662
0
}
663
664
/************************************************************************/
665
/*                      GetEstimatedRAMUsage()                          */
666
/************************************************************************/
667
668
/**
669
 * \brief Return the intrinsic RAM usage of this dataset.
670
 *
671
 * The returned value should take into account caches in the underlying driver
672
 * and decoding library, but not the usage related to the GDAL block cache.
673
 *
674
 * At time of writing, this method is only implemented in the JP2OpenJPEG
675
 * driver. For single-tiled JPEG2000 images, the decoding of the image,
676
 * even partially, involves allocating at least
677
 * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
678
 * library.
679
 *
680
 * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
681
 * driver, to determine how long a dataset in the pool must be kept open, given
682
 * the RAM usage of the dataset with respect to the usable total RAM.
683
 *
684
 * @since GDAL 3.7
685
 * @return RAM usage in bytes, or -1 if unknown (the default implementation
686
 * returns -1)
687
 */
688
689
GIntBig GDALDataset::GetEstimatedRAMUsage()
690
0
{
691
0
    return -1;
692
0
}
693
694
/************************************************************************/
695
/*                        BlockBasedFlushCache()                        */
696
/*                                                                      */
697
/*      This helper method can be called by the                         */
698
/*      GDALDataset::FlushCache() for particular drivers to ensure      */
699
/*      that buffers will be flushed in a manner suitable for pixel     */
700
/*      interleaved (by block) IO.  That is, if all the bands have      */
701
/*      the same size blocks then a given block will be flushed for     */
702
/*      all bands before proceeding to the next block.                  */
703
/************************************************************************/
704
705
//! @cond Doxygen_Suppress
706
CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
707
708
0
{
709
0
    GDALRasterBand *poBand1 = GetRasterBand(1);
710
0
    if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
711
0
    {
712
0
        return GDALDataset::FlushCache(bAtClosing);
713
0
    }
714
715
0
    int nBlockXSize = 0;
716
0
    int nBlockYSize = 0;
717
0
    poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
718
719
    /* -------------------------------------------------------------------- */
720
    /*      Verify that all bands match.                                    */
721
    /* -------------------------------------------------------------------- */
722
0
    for (int iBand = 1; iBand < nBands; ++iBand)
723
0
    {
724
0
        GDALRasterBand *poBand = GetRasterBand(iBand + 1);
725
726
0
        int nThisBlockXSize, nThisBlockYSize;
727
0
        poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
728
0
        if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
729
0
        {
730
0
            return GDALDataset::FlushCache(bAtClosing);
731
0
        }
732
0
    }
733
734
    /* -------------------------------------------------------------------- */
735
    /*      Now flush writable data.                                        */
736
    /* -------------------------------------------------------------------- */
737
0
    for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
738
0
    {
739
0
        for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
740
0
        {
741
0
            for (int iBand = 0; iBand < nBands; ++iBand)
742
0
            {
743
0
                const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);
744
745
0
                if (eErr != CE_None)
746
0
                    return CE_Failure;
747
0
            }
748
0
        }
749
0
    }
750
0
    return CE_None;
751
0
}
752
753
/************************************************************************/
754
/*                          RasterInitialize()                          */
755
/*                                                                      */
756
/*      Initialize raster size                                          */
757
/************************************************************************/
758
759
void GDALDataset::RasterInitialize(int nXSize, int nYSize)
760
761
0
{
762
0
    CPLAssert(nXSize > 0 && nYSize > 0);
763
764
0
    nRasterXSize = nXSize;
765
0
    nRasterYSize = nYSize;
766
0
}
767
768
//! @endcond
769
770
/************************************************************************/
771
/*                              AddBand()                               */
772
/************************************************************************/
773
774
/**
775
 * \fn GDALDataset::AddBand(GDALDataType, char**)
776
 * \brief Add a band to a dataset.
777
 *
778
 * This method will add a new band to the dataset if the underlying format
779
 * supports this action.  Most formats do not.
780
 *
781
 * Note that the new GDALRasterBand is not returned.  It may be fetched
782
 * after successful completion of the method by calling
783
 * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
784
 * band will always be the last band.
785
 *
786
 * @param eType the data type of the pixels in the new band.
787
 *
788
 * @param papszOptions a list of NAME=VALUE option strings.  The supported
789
 * options are format specific.  NULL may be passed by default.
790
 *
791
 * @return CE_None on success or CE_Failure on failure.
792
 */
793
794
CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
795
                            CPL_UNUSED char **papszOptions)
796
797
0
{
798
0
    ReportError(CE_Failure, CPLE_NotSupported,
799
0
                "Dataset does not support the AddBand() method.");
800
801
0
    return CE_Failure;
802
0
}
803
804
/************************************************************************/
805
/*                            GDALAddBand()                             */
806
/************************************************************************/
807
808
/**
809
 * \brief Add a band to a dataset.
810
 *
811
 * @see GDALDataset::AddBand().
812
 */
813
814
CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
815
                               CSLConstList papszOptions)
816
817
0
{
818
0
    VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
819
820
0
    return GDALDataset::FromHandle(hDataset)->AddBand(
821
0
        eType, const_cast<char **>(papszOptions));
822
0
}
823
824
/************************************************************************/
825
/*                              SetBand()                               */
826
/************************************************************************/
827
828
//! @cond Doxygen_Suppress
829
/**  Set a band in the band array, updating the band count, and array size
830
 * appropriately.
831
 *
832
 * @param nNewBand new band number (indexing starts at 1)
833
 * @param poBand band object.
834
 */
835
836
void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
837
838
0
{
839
    /* -------------------------------------------------------------------- */
840
    /*      Do we need to grow the bands list?                              */
841
    /* -------------------------------------------------------------------- */
842
0
    if (nBands < nNewBand || papoBands == nullptr)
843
0
    {
844
0
        GDALRasterBand **papoNewBands = nullptr;
845
846
0
        if (papoBands == nullptr)
847
0
            papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
848
0
                sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
849
0
        else
850
0
            papoNewBands = static_cast<GDALRasterBand **>(
851
0
                VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
852
0
                                          std::max(nNewBand, nBands)));
853
0
        if (papoNewBands == nullptr)
854
0
        {
855
0
            ReportError(CE_Failure, CPLE_OutOfMemory,
856
0
                        "Cannot allocate band array");
857
0
            return;
858
0
        }
859
860
0
        papoBands = papoNewBands;
861
862
0
        for (int i = nBands; i < nNewBand; ++i)
863
0
            papoBands[i] = nullptr;
864
865
0
        nBands = std::max(nBands, nNewBand);
866
867
0
        if (m_poPrivate)
868
0
        {
869
0
            for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
870
0
                 i < nBands; ++i)
871
0
            {
872
0
                m_poPrivate->m_anBandMap.push_back(i + 1);
873
0
            }
874
0
        }
875
0
    }
876
877
    /* -------------------------------------------------------------------- */
878
    /*      Set the band.  Resetting the band is currently not permitted.   */
879
    /* -------------------------------------------------------------------- */
880
0
    if (papoBands[nNewBand - 1] != nullptr)
881
0
    {
882
0
        ReportError(CE_Failure, CPLE_NotSupported,
883
0
                    "Cannot set band %d as it is already set", nNewBand);
884
0
        return;
885
0
    }
886
887
0
    papoBands[nNewBand - 1] = poBand;
888
889
    /* -------------------------------------------------------------------- */
890
    /*      Set back reference information on the raster band.  Note        */
891
    /*      that the GDALDataset is a friend of the GDALRasterBand          */
892
    /*      specifically to allow this.                                     */
893
    /* -------------------------------------------------------------------- */
894
0
    poBand->nBand = nNewBand;
895
0
    poBand->poDS = this;
896
0
    poBand->nRasterXSize = nRasterXSize;
897
0
    poBand->nRasterYSize = nRasterYSize;
898
0
    poBand->eAccess = eAccess;  // Default access to be same as dataset.
899
0
}
900
901
//! @endcond
902
903
/************************************************************************/
904
/*                              SetBand()                               */
905
/************************************************************************/
906
907
//! @cond Doxygen_Suppress
908
/**  Set a band in the band array, updating the band count, and array size
909
 * appropriately.
910
 *
911
 * @param nNewBand new band number (indexing starts at 1)
912
 * @param poBand band object.
913
 */
914
915
void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
916
0
{
917
0
    SetBand(nNewBand, poBand.release());
918
0
}
919
920
//! @endcond
921
922
/************************************************************************/
923
/*                           GetRasterXSize()                           */
924
/************************************************************************/
925
926
/**
927
928
 \brief Fetch raster width in pixels.
929
930
 Equivalent of the C function GDALGetRasterXSize().
931
932
 @return the width in pixels of raster bands in this GDALDataset.
933
934
*/
935
936
int GDALDataset::GetRasterXSize() const
937
0
{
938
0
    return nRasterXSize;
939
0
}
940
941
/************************************************************************/
942
/*                         GDALGetRasterXSize()                         */
943
/************************************************************************/
944
945
/**
946
 * \brief Fetch raster width in pixels.
947
 *
948
 * @see GDALDataset::GetRasterXSize().
949
 */
950
951
int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
952
953
0
{
954
0
    VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
955
956
0
    return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
957
0
}
958
959
/************************************************************************/
960
/*                           GetRasterYSize()                           */
961
/************************************************************************/
962
963
/**
964
965
 \brief Fetch raster height in pixels.
966
967
 Equivalent of the C function GDALGetRasterYSize().
968
969
 @return the height in pixels of raster bands in this GDALDataset.
970
971
*/
972
973
int GDALDataset::GetRasterYSize() const
974
0
{
975
0
    return nRasterYSize;
976
0
}
977
978
/************************************************************************/
979
/*                         GDALGetRasterYSize()                         */
980
/************************************************************************/
981
982
/**
983
 * \brief Fetch raster height in pixels.
984
 *
985
 * @see GDALDataset::GetRasterYSize().
986
 */
987
988
int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
989
990
0
{
991
0
    VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
992
993
0
    return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
994
0
}
995
996
/************************************************************************/
997
/*                           GetRasterBand()                            */
998
/************************************************************************/
999
1000
/**
1001
1002
 \brief Fetch a band object for a dataset.
1003
1004
 See GetBands() for a C++ iterator version of this method.
1005
1006
 Equivalent of the C function GDALGetRasterBand().
1007
1008
 @param nBandId the index number of the band to fetch, from 1 to
1009
                GetRasterCount().
1010
1011
 @return the nBandId th band object
1012
1013
*/
1014
1015
GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1016
1017
0
{
1018
0
    if (papoBands)
1019
0
    {
1020
0
        if (nBandId < 1 || nBandId > nBands)
1021
0
        {
1022
0
            ReportError(CE_Failure, CPLE_IllegalArg,
1023
0
                        "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1024
0
                        nBandId);
1025
0
            return nullptr;
1026
0
        }
1027
1028
0
        return papoBands[nBandId - 1];
1029
0
    }
1030
0
    return nullptr;
1031
0
}
1032
1033
/************************************************************************/
1034
/*                           GetRasterBand()                            */
1035
/************************************************************************/
1036
1037
/**
1038
1039
 \brief Fetch a band object for a dataset.
1040
1041
 See GetBands() for a C++ iterator version of this method.
1042
1043
 Equivalent of the C function GDALGetRasterBand().
1044
1045
 @param nBandId the index number of the band to fetch, from 1 to
1046
                GetRasterCount().
1047
1048
 @return the nBandId th band object
1049
1050
*/
1051
1052
const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1053
1054
0
{
1055
0
    if (papoBands)
1056
0
    {
1057
0
        if (nBandId < 1 || nBandId > nBands)
1058
0
        {
1059
0
            ReportError(CE_Failure, CPLE_IllegalArg,
1060
0
                        "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1061
0
                        nBandId);
1062
0
            return nullptr;
1063
0
        }
1064
1065
0
        return papoBands[nBandId - 1];
1066
0
    }
1067
0
    return nullptr;
1068
0
}
1069
1070
/************************************************************************/
1071
/*                         GDALGetRasterBand()                          */
1072
/************************************************************************/
1073
1074
/**
1075
 * \brief Fetch a band object for a dataset.
1076
 * @see GDALDataset::GetRasterBand().
1077
 */
1078
1079
GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1080
1081
0
{
1082
0
    VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1083
1084
0
    return GDALRasterBand::ToHandle(
1085
0
        GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
1086
0
}
1087
1088
/************************************************************************/
1089
/*                           GetRasterCount()                           */
1090
/************************************************************************/
1091
1092
/**
1093
 * \brief Fetch the number of raster bands on this dataset.
1094
 *
1095
 * Same as the C function GDALGetRasterCount().
1096
 *
1097
 * @return the number of raster bands.
1098
 */
1099
1100
int GDALDataset::GetRasterCount() const
1101
0
{
1102
0
    return papoBands ? nBands : 0;
1103
0
}
1104
1105
/************************************************************************/
1106
/*                         GDALGetRasterCount()                         */
1107
/************************************************************************/
1108
1109
/**
1110
 * \brief Fetch the number of raster bands on this dataset.
1111
 *
1112
 * @see GDALDataset::GetRasterCount().
1113
 */
1114
1115
int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1116
1117
0
{
1118
0
    VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1119
1120
0
    return GDALDataset::FromHandle(hDS)->GetRasterCount();
1121
0
}
1122
1123
/************************************************************************/
1124
/*                          GetProjectionRef()                          */
1125
/************************************************************************/
1126
1127
/**
1128
 * \brief Fetch the projection definition string for this dataset.
1129
 *
1130
 * Same as the C function GDALGetProjectionRef().
1131
 *
1132
 * The returned string defines the projection coordinate system of the
1133
 * image in OpenGIS WKT format.  It should be suitable for use with the
1134
 * OGRSpatialReference class.
1135
 *
1136
 * When a projection definition is not available an empty (but not NULL)
1137
 * string is returned.
1138
 *
1139
 * \note Starting with GDAL 3.0, this is a compatibility layer around
1140
 * GetSpatialRef()
1141
 *
1142
 * @return a pointer to an internal projection reference string.  It should
1143
 * not be altered, freed or expected to last for long.
1144
 *
1145
 * @see https://gdal.org/tutorials/osr_api_tut.html
1146
 */
1147
1148
const char *GDALDataset::GetProjectionRef() const
1149
0
{
1150
0
    const auto poSRS = GetSpatialRef();
1151
0
    if (!poSRS || !m_poPrivate)
1152
0
    {
1153
0
        return "";
1154
0
    }
1155
0
    char *pszWKT = nullptr;
1156
0
    poSRS->exportToWkt(&pszWKT);
1157
0
    if (!pszWKT)
1158
0
    {
1159
0
        return "";
1160
0
    }
1161
1162
    // If called on a thread-safe dataset, we might be called by several
1163
    // threads, so make sure our accesses to m_pszWKTCached are protected
1164
    // by a mutex.
1165
0
    std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1166
0
    if (m_poPrivate->m_pszWKTCached &&
1167
0
        strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1168
0
    {
1169
0
        CPLFree(pszWKT);
1170
0
        return m_poPrivate->m_pszWKTCached;
1171
0
    }
1172
0
    CPLFree(m_poPrivate->m_pszWKTCached);
1173
0
    m_poPrivate->m_pszWKTCached = pszWKT;
1174
0
    return m_poPrivate->m_pszWKTCached;
1175
0
}
1176
1177
/************************************************************************/
1178
/*                           GetSpatialRef()                            */
1179
/************************************************************************/
1180
1181
/**
1182
 * \brief Fetch the spatial reference for this dataset.
1183
 *
1184
 * Same as the C function GDALGetSpatialRef().
1185
 *
1186
 * When a projection definition is not available, null is returned. If used on
1187
 * a dataset where there are GCPs and not a geotransform, this method returns
1188
 * null. Use GetGCPSpatialRef() instead.
1189
 *
1190
 * @since GDAL 3.0
1191
 *
1192
 * @return a pointer to an internal object. It should not be altered or freed.
1193
 * Its lifetime will be the one of the dataset object, or until the next
1194
 * call to this method.
1195
 *
1196
 * @see https://gdal.org/tutorials/osr_api_tut.html
1197
 */
1198
1199
const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1200
0
{
1201
0
    return nullptr;
1202
0
}
1203
1204
/************************************************************************/
1205
/*                        GDALGetSpatialRef()                           */
1206
/************************************************************************/
1207
1208
/**
1209
 * \brief Fetch the spatial reference for this dataset.
1210
 *
1211
 * @since GDAL 3.0
1212
 *
1213
 * @see GDALDataset::GetSpatialRef()
1214
 */
1215
1216
OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1217
1218
0
{
1219
0
    VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1220
1221
0
    return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1222
0
        GDALDataset::FromHandle(hDS)->GetSpatialRef()));
1223
0
}
1224
1225
/************************************************************************/
1226
/*                        GDALGetProjectionRef()                        */
1227
/************************************************************************/
1228
1229
/**
1230
 * \brief Fetch the projection definition string for this dataset.
1231
 *
1232
 * @see GDALDataset::GetProjectionRef()
1233
 */
1234
1235
const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1236
1237
0
{
1238
0
    VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1239
1240
0
    return GDALDataset::FromHandle(hDS)->GetProjectionRef();
1241
0
}
1242
1243
/************************************************************************/
1244
/*                           SetProjection()                            */
1245
/************************************************************************/
1246
1247
/**
1248
 * \brief Set the projection reference string for this dataset.
1249
 *
1250
 * The string should be in OGC WKT or PROJ.4 format.  An error may occur
1251
 * because of incorrectly specified projection strings, because the dataset
1252
 * is not writable, or because the dataset does not support the indicated
1253
 * projection.  Many formats do not support writing projections.
1254
 *
1255
 * This method is the same as the C GDALSetProjection() function.
1256
 *
1257
 * \note Startig with GDAL 3.0, this is a compatibility layer around
1258
 * SetSpatialRef()
1259
1260
 * @param pszProjection projection reference string.
1261
 *
1262
 * @return CE_Failure if an error occurs, otherwise CE_None.
1263
 */
1264
1265
CPLErr GDALDataset::SetProjection(const char *pszProjection)
1266
0
{
1267
0
    if (pszProjection && pszProjection[0] != '\0')
1268
0
    {
1269
0
        OGRSpatialReference oSRS;
1270
0
        oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1271
0
        if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1272
0
        {
1273
0
            return CE_Failure;
1274
0
        }
1275
0
        return SetSpatialRef(&oSRS);
1276
0
    }
1277
0
    else
1278
0
    {
1279
0
        return SetSpatialRef(nullptr);
1280
0
    }
1281
0
}
1282
1283
/************************************************************************/
1284
/*                           SetSpatialRef()                            */
1285
/************************************************************************/
1286
1287
/**
1288
 * \brief Set the spatial reference system for this dataset.
1289
 *
1290
 * An error may occur because the dataset
1291
 * is not writable, or because the dataset does not support the indicated
1292
 * projection. Many formats do not support writing projections.
1293
 *
1294
 * This method is the same as the C GDALSetSpatialRef() function.
1295
 *
1296
 * @since GDAL 3.0
1297
1298
 * @param poSRS spatial reference system object. nullptr can potentially be
1299
 * passed for drivers that support unsetting the SRS.
1300
 *
1301
 * @return CE_Failure if an error occurs, otherwise CE_None.
1302
 */
1303
1304
CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
1305
0
{
1306
0
    if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1307
0
        ReportError(CE_Failure, CPLE_NotSupported,
1308
0
                    "Dataset does not support the SetSpatialRef() method.");
1309
0
    return CE_Failure;
1310
0
}
1311
1312
/************************************************************************/
1313
/*                         GDALSetSpatialRef()                          */
1314
/************************************************************************/
1315
1316
/**
1317
 * \brief Set the spatial reference system for this dataset.
1318
 *
1319
 * @since GDAL 3.0
1320
 *
1321
 * @see GDALDataset::SetSpatialRef()
1322
 */
1323
1324
CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1325
1326
0
{
1327
0
    VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1328
1329
0
    return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1330
0
        OGRSpatialReference::FromHandle(hSRS));
1331
0
}
1332
1333
/************************************************************************/
1334
/*                         GDALSetProjection()                          */
1335
/************************************************************************/
1336
1337
/**
1338
 * \brief Set the projection reference string for this dataset.
1339
 *
1340
 * @see GDALDataset::SetProjection()
1341
 */
1342
1343
CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1344
                                     const char *pszProjection)
1345
1346
0
{
1347
0
    VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1348
1349
0
    return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1350
0
}
1351
1352
/************************************************************************/
1353
/*                          GetGeoTransform()                           */
1354
/************************************************************************/
1355
1356
/**
1357
 * \brief Fetch the affine transformation coefficients.
1358
 *
1359
 * Fetches the coefficients for transforming between pixel/line (P,L) raster
1360
 * space, and projection coordinates (Xp,Yp) space.
1361
 *
1362
 * \code
1363
 *   Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1364
 *   Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1365
 * \endcode
1366
 *
1367
 * In a north up image, padfTransform[1] is the pixel width, and
1368
 * padfTransform[5] is the pixel height.  The upper left corner of the
1369
 * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1370
 *
1371
 * The default transform is (0,1,0,0,0,1) and should be returned even when
1372
 * a CE_Failure error is returned, such as for formats that don't support
1373
 * transformation to projection coordinates.
1374
 *
1375
 * This method does the same thing as the C GDALGetGeoTransform() function.
1376
 *
1377
 * @param padfTransform an existing six double buffer into which the
1378
 * transformation will be placed.
1379
 *
1380
 * @return CE_None on success, or CE_Failure if no transform can be fetched.
1381
 */
1382
1383
CPLErr GDALDataset::GetGeoTransform(double *padfTransform)
1384
1385
0
{
1386
0
    CPLAssert(padfTransform != nullptr);
1387
1388
0
    padfTransform[0] = 0.0;  // X Origin (top left corner)
1389
0
    padfTransform[1] = 1.0;  // X Pixel size */
1390
0
    padfTransform[2] = 0.0;
1391
1392
0
    padfTransform[3] = 0.0;  // Y Origin (top left corner)
1393
0
    padfTransform[4] = 0.0;
1394
0
    padfTransform[5] = 1.0;  // Y Pixel Size
1395
1396
0
    return CE_Failure;
1397
0
}
1398
1399
/************************************************************************/
1400
/*                        GDALGetGeoTransform()                         */
1401
/************************************************************************/
1402
1403
/**
1404
 * \brief Fetch the affine transformation coefficients.
1405
 *
1406
 * @see GDALDataset::GetGeoTransform()
1407
 */
1408
1409
CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1410
1411
0
{
1412
0
    VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1413
1414
0
    return GDALDataset::FromHandle(hDS)->GetGeoTransform(padfTransform);
1415
0
}
1416
1417
/************************************************************************/
1418
/*                          SetGeoTransform()                           */
1419
/************************************************************************/
1420
1421
/**
1422
 * \fn GDALDataset::SetGeoTransform(double*)
1423
 * \brief Set the affine transformation coefficients.
1424
 *
1425
 * See GetGeoTransform() for details on the meaning of the padfTransform
1426
 * coefficients.
1427
 *
1428
 * This method does the same thing as the C GDALSetGeoTransform() function.
1429
 *
1430
 * @param padfTransform a six double buffer containing the transformation
1431
 * coefficients to be written with the dataset.
1432
 *
1433
 * @return CE_None on success, or CE_Failure if this transform cannot be
1434
 * written.
1435
 */
1436
1437
CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED double *padfTransform)
1438
1439
0
{
1440
0
    if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1441
0
        ReportError(CE_Failure, CPLE_NotSupported,
1442
0
                    "SetGeoTransform() not supported for this dataset.");
1443
1444
0
    return CE_Failure;
1445
0
}
1446
1447
/************************************************************************/
1448
/*                        GDALSetGeoTransform()                         */
1449
/************************************************************************/
1450
1451
/**
1452
 * \brief Set the affine transformation coefficients.
1453
 *
1454
 * @see GDALDataset::SetGeoTransform()
1455
 */
1456
1457
CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1458
1459
0
{
1460
0
    VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1461
1462
0
    return GDALDataset::FromHandle(hDS)->SetGeoTransform(padfTransform);
1463
0
}
1464
1465
/************************************************************************/
1466
/*                         GetInternalHandle()                          */
1467
/************************************************************************/
1468
1469
/**
1470
 * \fn GDALDataset::GetInternalHandle(const char*)
1471
 * \brief Fetch a format specific internally meaningful handle.
1472
 *
1473
 * This method is the same as the C GDALGetInternalHandle() method.
1474
 *
1475
 * @param pszHandleName the handle name desired.  The meaningful names
1476
 * will be specific to the file format.
1477
 *
1478
 * @return the desired handle value, or NULL if not recognized/supported.
1479
 */
1480
1481
void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
1482
1483
0
{
1484
0
    return nullptr;
1485
0
}
1486
1487
/************************************************************************/
1488
/*                       GDALGetInternalHandle()                        */
1489
/************************************************************************/
1490
1491
/**
1492
 * \brief Fetch a format specific internally meaningful handle.
1493
 *
1494
 * @see GDALDataset::GetInternalHandle()
1495
 */
1496
1497
void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
1498
                                        const char *pszRequest)
1499
1500
0
{
1501
0
    VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1502
1503
0
    return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1504
0
}
1505
1506
/************************************************************************/
1507
/*                             GetDriver()                              */
1508
/************************************************************************/
1509
1510
/**
1511
 * \brief Fetch the driver to which this dataset relates.
1512
 *
1513
 * This method is the same as the C GDALGetDatasetDriver() function.
1514
 *
1515
 * @return the driver on which the dataset was created with GDALOpen() or
1516
 * GDALCreate().
1517
 */
1518
1519
GDALDriver *GDALDataset::GetDriver()
1520
0
{
1521
0
    return poDriver;
1522
0
}
1523
1524
/************************************************************************/
1525
/*                        GDALGetDatasetDriver()                        */
1526
/************************************************************************/
1527
1528
/**
1529
 * \brief Fetch the driver to which this dataset relates.
1530
 *
1531
 * @see GDALDataset::GetDriver()
1532
 */
1533
1534
GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1535
1536
0
{
1537
0
    VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1538
1539
0
    return static_cast<GDALDriverH>(
1540
0
        GDALDataset::FromHandle(hDataset)->GetDriver());
1541
0
}
1542
1543
/************************************************************************/
1544
/*                             Reference()                              */
1545
/************************************************************************/
1546
1547
/**
1548
 * \brief Add one to dataset reference count.
1549
 *
1550
 * The reference is one after instantiation.
1551
 *
1552
 * This method is the same as the C GDALReferenceDataset() function.
1553
 *
1554
 * @return the post-increment reference count.
1555
 */
1556
1557
int GDALDataset::Reference()
1558
0
{
1559
0
    return ++nRefCount;
1560
0
}
1561
1562
/************************************************************************/
1563
/*                        GDALReferenceDataset()                        */
1564
/************************************************************************/
1565
1566
/**
1567
 * \brief Add one to dataset reference count.
1568
 *
1569
 * @see GDALDataset::Reference()
1570
 */
1571
1572
int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1573
1574
0
{
1575
0
    VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1576
1577
0
    return GDALDataset::FromHandle(hDataset)->Reference();
1578
0
}
1579
1580
/************************************************************************/
1581
/*                            Dereference()                             */
1582
/************************************************************************/
1583
1584
/**
1585
 * \brief Subtract one from dataset reference count.
1586
 *
1587
 * The reference is one after instantiation.  Generally when the reference
1588
 * count has dropped to zero the dataset may be safely deleted (closed).
1589
 *
1590
 * This method is the same as the C GDALDereferenceDataset() function.
1591
 *
1592
 * @return the post-decrement reference count.
1593
 */
1594
1595
int GDALDataset::Dereference()
1596
0
{
1597
0
    return --nRefCount;
1598
0
}
1599
1600
/************************************************************************/
1601
/*                       GDALDereferenceDataset()                       */
1602
/************************************************************************/
1603
1604
/**
1605
 * \brief Subtract one from dataset reference count.
1606
 *
1607
 * @see GDALDataset::Dereference()
1608
 */
1609
1610
int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1611
1612
0
{
1613
0
    VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1614
1615
0
    return GDALDataset::FromHandle(hDataset)->Dereference();
1616
0
}
1617
1618
/************************************************************************/
1619
/*                            ReleaseRef()                              */
1620
/************************************************************************/
1621
1622
/**
1623
 * \brief Drop a reference to this object, and destroy if no longer referenced.
1624
 * @return TRUE if the object has been destroyed.
1625
 * @since GDAL 2.2
1626
 */
1627
1628
int GDALDataset::ReleaseRef()
1629
1630
0
{
1631
0
    if (Dereference() <= 0)
1632
0
    {
1633
0
        nRefCount = 1;
1634
0
        delete this;
1635
0
        return TRUE;
1636
0
    }
1637
0
    return FALSE;
1638
0
}
1639
1640
/************************************************************************/
1641
/*                        GDALReleaseDataset()                          */
1642
/************************************************************************/
1643
1644
/**
1645
 * \brief Drop a reference to this object, and destroy if no longer referenced.
1646
 *
1647
 * @see GDALDataset::ReleaseRef()
1648
 * @since GDAL 2.2
1649
 */
1650
1651
int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1652
1653
0
{
1654
0
    VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1655
1656
0
    return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1657
0
}
1658
1659
/************************************************************************/
1660
/*                             GetShared()                              */
1661
/************************************************************************/
1662
1663
/**
1664
 * \brief Returns shared flag.
1665
 *
1666
 * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1667
 */
1668
1669
int GDALDataset::GetShared() const
1670
0
{
1671
0
    return bShared;
1672
0
}
1673
1674
/************************************************************************/
1675
/*                            MarkAsShared()                            */
1676
/************************************************************************/
1677
1678
/**
1679
 * \brief Mark this dataset as available for sharing.
1680
 */
1681
1682
void GDALDataset::MarkAsShared()
1683
1684
0
{
1685
0
    CPLAssert(!bShared);
1686
1687
0
    bShared = true;
1688
0
    if (bIsInternal)
1689
0
        return;
1690
1691
0
    GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1692
1693
    // Insert the dataset in the set of shared opened datasets.
1694
0
    CPLMutexHolderD(&hDLMutex);
1695
0
    if (phSharedDatasetSet == nullptr)
1696
0
        phSharedDatasetSet =
1697
0
            CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1698
0
                          GDALSharedDatasetFreeFunc);
1699
1700
0
    SharedDatasetCtxt *psStruct =
1701
0
        static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1702
0
    psStruct->poDS = this;
1703
0
    psStruct->nPID = nPID;
1704
0
    psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1705
0
    psStruct->pszDescription = CPLStrdup(GetDescription());
1706
0
    std::string osConcatenatedOpenOptions =
1707
0
        GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1708
0
    psStruct->pszConcatenatedOpenOptions =
1709
0
        CPLStrdup(osConcatenatedOpenOptions.c_str());
1710
0
    if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1711
0
    {
1712
0
        GDALSharedDatasetFreeFunc(psStruct);
1713
0
        ReportError(CE_Failure, CPLE_AppDefined,
1714
0
                    "An existing shared dataset already has this description. "
1715
0
                    "This should not happen.");
1716
0
    }
1717
0
    else
1718
0
    {
1719
0
        CPLHashSetInsert(phSharedDatasetSet, psStruct);
1720
1721
0
        (*poAllDatasetMap)[this] = nPID;
1722
0
    }
1723
0
}
1724
1725
/************************************************************************/
1726
/*                        MarkSuppressOnClose()                         */
1727
/************************************************************************/
1728
1729
/** Set that the dataset must be deleted on close. */
1730
void GDALDataset::MarkSuppressOnClose()
1731
0
{
1732
0
    bSuppressOnClose = true;
1733
0
}
1734
1735
/************************************************************************/
1736
/*                       UnMarkSuppressOnClose()                        */
1737
/************************************************************************/
1738
1739
/** Remove the flag requesting the dataset to be deleted on close. */
1740
void GDALDataset::UnMarkSuppressOnClose()
1741
0
{
1742
0
    bSuppressOnClose = false;
1743
0
}
1744
1745
/************************************************************************/
1746
/*                        CleanupPostFileClosing()                      */
1747
/************************************************************************/
1748
1749
/** This method should be called by driver implementations in their destructor,
1750
 * after having closed all files, but before having freed resources that
1751
 * are needed for their GetFileList() implementation.
1752
 * This is used to implement MarkSuppressOnClose behavior.
1753
 */
1754
void GDALDataset::CleanupPostFileClosing()
1755
0
{
1756
0
    if (IsMarkedSuppressOnClose())
1757
0
    {
1758
0
        char **papszFileList = GetFileList();
1759
0
        for (int i = 0; papszFileList && papszFileList[i]; ++i)
1760
0
            VSIUnlink(papszFileList[i]);
1761
0
        CSLDestroy(papszFileList);
1762
0
    }
1763
0
}
1764
1765
/************************************************************************/
1766
/*                            GetGCPCount()                             */
1767
/************************************************************************/
1768
1769
/**
1770
 * \brief Get number of GCPs.
1771
 *
1772
 * This method is the same as the C function GDALGetGCPCount().
1773
 *
1774
 * @return number of GCPs for this dataset.  Zero if there are none.
1775
 */
1776
1777
int GDALDataset::GetGCPCount()
1778
0
{
1779
0
    return 0;
1780
0
}
1781
1782
/************************************************************************/
1783
/*                          GDALGetGCPCount()                           */
1784
/************************************************************************/
1785
1786
/**
1787
 * \brief Get number of GCPs.
1788
 *
1789
 * @see GDALDataset::GetGCPCount()
1790
 */
1791
1792
int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1793
1794
0
{
1795
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1796
1797
0
    return GDALDataset::FromHandle(hDS)->GetGCPCount();
1798
0
}
1799
1800
/************************************************************************/
1801
/*                          GetGCPProjection()                          */
1802
/************************************************************************/
1803
1804
/**
1805
 * \brief Get output projection for GCPs.
1806
 *
1807
 * This method is the same as the C function GDALGetGCPProjection().
1808
 *
1809
 * The projection string follows the normal rules from GetProjectionRef().
1810
 *
1811
 * \note Starting with GDAL 3.0, this is a compatibility layer around
1812
 * GetGCPSpatialRef()
1813
 *
1814
 * @return internal projection string or "" if there are no GCPs.
1815
 *  It should not be altered, freed or expected to last for long.
1816
 */
1817
1818
const char *GDALDataset::GetGCPProjection()
1819
0
{
1820
0
    const auto poSRS = GetGCPSpatialRef();
1821
0
    if (!poSRS || !m_poPrivate)
1822
0
    {
1823
0
        return "";
1824
0
    }
1825
0
    char *pszWKT = nullptr;
1826
0
    poSRS->exportToWkt(&pszWKT);
1827
0
    if (!pszWKT)
1828
0
    {
1829
0
        return "";
1830
0
    }
1831
1832
    // If called on a thread-safe dataset, we might be called by several
1833
    // threads, so make sure our accesses to m_pszWKTCached are protected
1834
    // by a mutex.
1835
0
    std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1836
0
    if (m_poPrivate->m_pszWKTGCPCached &&
1837
0
        strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
1838
0
    {
1839
0
        CPLFree(pszWKT);
1840
0
        return m_poPrivate->m_pszWKTGCPCached;
1841
0
    }
1842
0
    CPLFree(m_poPrivate->m_pszWKTGCPCached);
1843
0
    m_poPrivate->m_pszWKTGCPCached = pszWKT;
1844
0
    return m_poPrivate->m_pszWKTGCPCached;
1845
0
}
1846
1847
/************************************************************************/
1848
/*                          GetGCPSpatialRef()                          */
1849
/************************************************************************/
1850
1851
/**
1852
 * \brief Get output spatial reference system for GCPs.
1853
 *
1854
 * Same as the C function GDALGetGCPSpatialRef().
1855
 *
1856
 * When a SRS is not available, null is returned. If used on
1857
 * a dataset where there is a geotransform, and not GCPs, this method returns
1858
 * null. Use GetSpatialRef() instead.
1859
 *
1860
 * @since GDAL 3.0
1861
 *
1862
 * @return a pointer to an internal object. It should not be altered or freed.
1863
 * Its lifetime will be the one of the dataset object, or until the next
1864
 * call to this method.
1865
 */
1866
1867
const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
1868
0
{
1869
0
    return nullptr;
1870
0
}
1871
1872
/************************************************************************/
1873
/*                       GDALGetGCPSpatialRef()                         */
1874
/************************************************************************/
1875
1876
/**
1877
 * \brief Get output spatial reference system for GCPs.
1878
 *
1879
 * @since GDAL 3.0
1880
 *
1881
 * @see GDALDataset::GetGCPSpatialRef()
1882
 */
1883
1884
OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
1885
1886
0
{
1887
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1888
1889
0
    return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1890
0
        GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
1891
0
}
1892
1893
/************************************************************************/
1894
/*                        GDALGetGCPProjection()                        */
1895
/************************************************************************/
1896
1897
/**
1898
 * \brief Get output projection for GCPs.
1899
 *
1900
 * @see GDALDataset::GetGCPProjection()
1901
 */
1902
1903
const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
1904
1905
0
{
1906
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1907
1908
0
    return GDALDataset::FromHandle(hDS)->GetGCPProjection();
1909
0
}
1910
1911
/************************************************************************/
1912
/*                               GetGCPs()                              */
1913
/************************************************************************/
1914
1915
/**
1916
 * \brief Fetch GCPs.
1917
 *
1918
 * This method is the same as the C function GDALGetGCPs().
1919
 *
1920
 * @return pointer to internal GCP structure list.  It should not be modified,
1921
 * and may change on the next GDAL call.
1922
 */
1923
1924
const GDAL_GCP *GDALDataset::GetGCPs()
1925
0
{
1926
0
    return nullptr;
1927
0
}
1928
1929
/************************************************************************/
1930
/*                            GDALGetGCPs()                             */
1931
/************************************************************************/
1932
1933
/**
1934
 * \brief Fetch GCPs.
1935
 *
1936
 * @see GDALDataset::GetGCPs()
1937
 */
1938
1939
const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
1940
1941
0
{
1942
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
1943
1944
0
    return GDALDataset::FromHandle(hDS)->GetGCPs();
1945
0
}
1946
1947
/************************************************************************/
1948
/*                              SetGCPs()                               */
1949
/************************************************************************/
1950
1951
/**
1952
 * \brief Assign GCPs.
1953
 *
1954
 * This method is the same as the C function GDALSetGCPs().
1955
 *
1956
 * This method assigns the passed set of GCPs to this dataset, as well as
1957
 * setting their coordinate system.  Internally copies are made of the
1958
 * coordinate system and list of points, so the caller remains responsible for
1959
 * deallocating these arguments if appropriate.
1960
 *
1961
 * Most formats do not support setting of GCPs, even formats that can
1962
 * handle GCPs.  These formats will return CE_Failure.
1963
 *
1964
 * \note Startig with GDAL 3.0, this is a compatibility layer around
1965
 * SetGCPs(int, const GDAL_GCP*, const char*)
1966
 *
1967
 * @param nGCPCount number of GCPs being assigned.
1968
 *
1969
 * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1970
 *
1971
 * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
1972
 * GCP output coordinates.  This parameter should be "" if no output coordinate
1973
 * system is known.
1974
 *
1975
 * @return CE_None on success, CE_Failure on failure (including if action is
1976
 * not supported for this format).
1977
 */
1978
1979
CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
1980
                            const char *pszGCPProjection)
1981
1982
0
{
1983
0
    if (pszGCPProjection && pszGCPProjection[0] != '\0')
1984
0
    {
1985
0
        OGRSpatialReference oSRS;
1986
0
        oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1987
0
        if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
1988
0
        {
1989
0
            return CE_Failure;
1990
0
        }
1991
0
        return SetGCPs(nGCPCount, pasGCPList, &oSRS);
1992
0
    }
1993
0
    else
1994
0
    {
1995
0
        return SetGCPs(nGCPCount, pasGCPList,
1996
0
                       static_cast<const OGRSpatialReference *>(nullptr));
1997
0
    }
1998
0
}
1999
2000
/************************************************************************/
2001
/*                              SetGCPs()                               */
2002
/************************************************************************/
2003
2004
/**
2005
 * \brief Assign GCPs.
2006
 *
2007
 * This method is the same as the C function GDALSetGCPs().
2008
 *
2009
 * This method assigns the passed set of GCPs to this dataset, as well as
2010
 * setting their coordinate system.  Internally copies are made of the
2011
 * coordinate system and list of points, so the caller remains responsible for
2012
 * deallocating these arguments if appropriate.
2013
 *
2014
 * Most formats do not support setting of GCPs, even formats that can
2015
 * handle GCPs.  These formats will return CE_Failure.
2016
 *
2017
 * @since GDAL 3.0
2018
 *
2019
 * @param nGCPCount number of GCPs being assigned.
2020
 *
2021
 * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2022
 *
2023
 * @param poGCP_SRS the new coordinate reference system to assign for the
2024
 * GCP output coordinates.  This parameter should be null if no output
2025
 * coordinate system is known.
2026
 *
2027
 * @return CE_None on success, CE_Failure on failure (including if action is
2028
 * not supported for this format).
2029
 */
2030
2031
CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2032
                            CPL_UNUSED const GDAL_GCP *pasGCPList,
2033
                            CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2034
2035
0
{
2036
0
    if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2037
0
        ReportError(CE_Failure, CPLE_NotSupported,
2038
0
                    "Dataset does not support the SetGCPs() method.");
2039
2040
0
    return CE_Failure;
2041
0
}
2042
2043
/************************************************************************/
2044
/*                            GDALSetGCPs()                             */
2045
/************************************************************************/
2046
2047
/**
2048
 * \brief Assign GCPs.
2049
 *
2050
 * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
2051
 */
2052
2053
CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2054
                               const GDAL_GCP *pasGCPList,
2055
                               const char *pszGCPProjection)
2056
2057
0
{
2058
0
    VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2059
2060
0
    return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2061
0
                                                 pszGCPProjection);
2062
0
}
2063
2064
/************************************************************************/
2065
/*                           GDALSetGCPs2()                             */
2066
/************************************************************************/
2067
2068
/**
2069
 * \brief Assign GCPs.
2070
 *
2071
 * @since GDAL 3.0
2072
 * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
2073
 */
2074
2075
CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
2076
                    OGRSpatialReferenceH hSRS)
2077
2078
0
{
2079
0
    VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
2080
2081
0
    return GDALDataset::FromHandle(hDS)->SetGCPs(
2082
0
        nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
2083
0
}
2084
2085
/************************************************************************/
2086
/*                           BuildOverviews()                           */
2087
/************************************************************************/
2088
2089
/**
2090
 * \brief Build raster overview(s)
2091
 *
2092
 * If the operation is unsupported for the indicated dataset, then
2093
 * CE_Failure is returned, and CPLGetLastErrorNo() will return
2094
 * CPLE_NotSupported.
2095
 *
2096
 * Depending on the actual file format, all overviews level can be also
2097
 * deleted by specifying nOverviews == 0. This works at least for external
2098
 * overviews (.ovr), TIFF internal overviews, etc.
2099
 *
2100
 * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
2101
 * to "ALL_CPUS" or a integer value to specify the number of threads to use for
2102
 * overview computation.
2103
 *
2104
 * This method is the same as the C function GDALBuildOverviewsEx().
2105
 *
2106
 * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
2107
 * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
2108
 * or "NONE" controlling the downsampling method applied.
2109
 * @param nOverviews number of overviews to build, or 0 to clean overviews.
2110
 * @param panOverviewList the list of overview decimation factors (positive
2111
 *                        integers, normally larger or equal to 2) to build, or
2112
 *                        NULL if nOverviews == 0.
2113
 * @param nListBands number of bands to build overviews for in panBandList.
2114
 * Build for all bands if this is 0.
2115
 * @param panBandList list of band numbers.
2116
 * @param pfnProgress a function to call to report progress, or NULL.
2117
 * @param pProgressData application data to pass to the progress function.
2118
 * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
2119
 *                     key=value pairs, or NULL
2120
 *
2121
 * @return CE_None on success or CE_Failure if the operation doesn't work.
2122
 *
2123
 * For example, to build overview level 2, 4 and 8 on all bands the following
2124
 * call could be made:
2125
 * \code{.cpp}
2126
 *   int       anOverviewList[3] = { 2, 4, 8 };
2127
 *
2128
 *   poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
2129
 *                              GDALDummyProgress, nullptr );
2130
 * \endcode
2131
 *
2132
 * @see GDALRegenerateOverviewsEx()
2133
 */
2134
2135
CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
2136
                                   const int *panOverviewList, int nListBands,
2137
                                   const int *panBandList,
2138
                                   GDALProgressFunc pfnProgress,
2139
                                   void *pProgressData,
2140
                                   CSLConstList papszOptions)
2141
0
{
2142
0
    int *panAllBandList = nullptr;
2143
2144
0
    if (nListBands == 0)
2145
0
    {
2146
0
        nListBands = GetRasterCount();
2147
0
        panAllBandList =
2148
0
            static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2149
0
        for (int i = 0; i < nListBands; ++i)
2150
0
            panAllBandList[i] = i + 1;
2151
2152
0
        panBandList = panAllBandList;
2153
0
    }
2154
2155
0
    if (pfnProgress == nullptr)
2156
0
        pfnProgress = GDALDummyProgress;
2157
2158
0
    for (int i = 0; i < nOverviews; ++i)
2159
0
    {
2160
0
        if (panOverviewList[i] <= 0)
2161
0
        {
2162
0
            CPLError(CE_Failure, CPLE_IllegalArg,
2163
0
                     "panOverviewList[%d] = %d is invalid. It must be a "
2164
0
                     "positive value",
2165
0
                     i, panOverviewList[i]);
2166
0
            CPLFree(panAllBandList);
2167
0
            return CE_Failure;
2168
0
        }
2169
0
    }
2170
2171
    // At time of writing, all overview generation options are actually
2172
    // expected to be passed as configuration options.
2173
0
    std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;
2174
0
    for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(papszOptions))
2175
0
    {
2176
0
        apoConfigOptionSetter.emplace_back(
2177
0
            std::make_unique<CPLConfigOptionSetter>(pszKey, pszValue, false));
2178
0
    }
2179
2180
0
    const CPLErr eErr =
2181
0
        IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
2182
0
                        panBandList, pfnProgress, pProgressData, papszOptions);
2183
2184
0
    if (panAllBandList != nullptr)
2185
0
        CPLFree(panAllBandList);
2186
2187
0
    return eErr;
2188
0
}
2189
2190
/************************************************************************/
2191
/*                         GDALBuildOverviews()                         */
2192
/************************************************************************/
2193
2194
/**
2195
 * \brief Build raster overview(s)
2196
 *
2197
 * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
2198
 */
2199
2200
CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
2201
                                      const char *pszResampling, int nOverviews,
2202
                                      const int *panOverviewList,
2203
                                      int nListBands, const int *panBandList,
2204
                                      GDALProgressFunc pfnProgress,
2205
                                      void *pProgressData)
2206
2207
0
{
2208
0
    VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2209
2210
0
    return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2211
0
        pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2212
0
        pfnProgress, pProgressData, nullptr);
2213
0
}
2214
2215
/************************************************************************/
2216
/*                         GDALBuildOverviews()                         */
2217
/************************************************************************/
2218
2219
/**
2220
 * \brief Build raster overview(s)
2221
 *
2222
 * @see GDALDataset::BuildOverviews()
2223
 * @since GDAL 3.6
2224
 */
2225
2226
CPLErr CPL_STDCALL
2227
GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
2228
                     int nOverviews, const int *panOverviewList, int nListBands,
2229
                     const int *panBandList, GDALProgressFunc pfnProgress,
2230
                     void *pProgressData, CSLConstList papszOptions)
2231
2232
0
{
2233
0
    VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2234
2235
0
    return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2236
0
        pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2237
0
        pfnProgress, pProgressData, papszOptions);
2238
0
}
2239
2240
/************************************************************************/
2241
/*                          IBuildOverviews()                           */
2242
/*                                                                      */
2243
/*      Default implementation.                                         */
2244
/************************************************************************/
2245
2246
//! @cond Doxygen_Suppress
2247
CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
2248
                                    const int *panOverviewList, int nListBands,
2249
                                    const int *panBandList,
2250
                                    GDALProgressFunc pfnProgress,
2251
                                    void *pProgressData,
2252
                                    CSLConstList papszOptions)
2253
2254
0
{
2255
0
    if (oOvManager.IsInitialized())
2256
0
        return oOvManager.BuildOverviews(
2257
0
            nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2258
0
            panBandList, pfnProgress, pProgressData, papszOptions);
2259
0
    else
2260
0
    {
2261
0
        ReportError(CE_Failure, CPLE_NotSupported,
2262
0
                    "BuildOverviews() not supported for this dataset.");
2263
2264
0
        return CE_Failure;
2265
0
    }
2266
0
}
2267
2268
//! @endcond
2269
2270
/************************************************************************/
2271
/*                             IRasterIO()                              */
2272
/*                                                                      */
2273
/*      The default implementation of IRasterIO() is, in the general    */
2274
/*      case to pass the request off to each band objects rasterio      */
2275
/*      methods with appropriate arguments. In some cases, it might     */
2276
/*      choose instead the BlockBasedRasterIO() implementation.         */
2277
/************************************************************************/
2278
2279
//! @cond Doxygen_Suppress
2280
CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2281
                              int nXSize, int nYSize, void *pData,
2282
                              int nBufXSize, int nBufYSize,
2283
                              GDALDataType eBufType, int nBandCount,
2284
                              BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
2285
                              GSpacing nLineSpace, GSpacing nBandSpace,
2286
                              GDALRasterIOExtraArg *psExtraArg)
2287
2288
0
{
2289
0
    const char *pszInterleave = nullptr;
2290
2291
0
    CPLAssert(nullptr != pData);
2292
2293
0
    const bool bHasSubpixelShift =
2294
0
        psExtraArg->bFloatingPointWindowValidity &&
2295
0
        psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2296
0
        (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2297
2298
0
    if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2299
0
        nBandCount > 1 &&
2300
0
        (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2301
0
            nullptr &&
2302
0
        EQUAL(pszInterleave, "PIXEL"))
2303
0
    {
2304
0
        return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2305
0
                                  nBufXSize, nBufYSize, eBufType, nBandCount,
2306
0
                                  panBandMap, nPixelSpace, nLineSpace,
2307
0
                                  nBandSpace, psExtraArg);
2308
0
    }
2309
2310
0
    if (eRWFlag == GF_Read &&
2311
0
        (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2312
0
         psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2313
0
         psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2314
0
         psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2315
0
        !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2316
0
    {
2317
0
        if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2318
0
        {
2319
0
            int bTried = FALSE;
2320
0
            const CPLErr eErr = TryOverviewRasterIO(
2321
0
                eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2322
0
                nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2323
0
                nLineSpace, nBandSpace, psExtraArg, &bTried);
2324
0
            if (bTried)
2325
0
                return eErr;
2326
0
        }
2327
2328
0
        GDALDataType eFirstBandDT = GDT_Unknown;
2329
0
        int nFirstMaskFlags = 0;
2330
0
        GDALRasterBand *poFirstMaskBand = nullptr;
2331
0
        int nOKBands = 0;
2332
2333
        // Check if bands share the same mask band
2334
0
        for (int i = 0; i < nBandCount; ++i)
2335
0
        {
2336
0
            GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2337
0
            if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2338
0
                poBand->GetOverviewCount())
2339
0
            {
2340
                // Could be improved to select the appropriate overview.
2341
0
                break;
2342
0
            }
2343
0
            if (poBand->GetColorTable() != nullptr)
2344
0
            {
2345
0
                break;
2346
0
            }
2347
0
            const GDALDataType eDT = poBand->GetRasterDataType();
2348
0
            if (GDALDataTypeIsComplex(eDT))
2349
0
            {
2350
0
                break;
2351
0
            }
2352
0
            if (i == 0)
2353
0
            {
2354
0
                eFirstBandDT = eDT;
2355
0
                nFirstMaskFlags = poBand->GetMaskFlags();
2356
0
                if (nFirstMaskFlags == GMF_NODATA)
2357
0
                {
2358
                    // The dataset-level resampling code is not ready for nodata
2359
                    // Fallback to band-level resampling
2360
0
                    break;
2361
0
                }
2362
0
                poFirstMaskBand = poBand->GetMaskBand();
2363
0
            }
2364
0
            else
2365
0
            {
2366
0
                if (eDT != eFirstBandDT)
2367
0
                {
2368
0
                    break;
2369
0
                }
2370
0
                int nMaskFlags = poBand->GetMaskFlags();
2371
0
                if (nMaskFlags == GMF_NODATA)
2372
0
                {
2373
                    // The dataset-level resampling code is not ready for nodata
2374
                    // Fallback to band-level resampling
2375
0
                    break;
2376
0
                }
2377
0
                GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2378
0
                if (nFirstMaskFlags == GMF_ALL_VALID &&
2379
0
                    nMaskFlags == GMF_ALL_VALID)
2380
0
                {
2381
                    // Ok.
2382
0
                }
2383
0
                else if (poFirstMaskBand == poMaskBand)
2384
0
                {
2385
                    // Ok.
2386
0
                }
2387
0
                else
2388
0
                {
2389
0
                    break;
2390
0
                }
2391
0
            }
2392
2393
0
            ++nOKBands;
2394
0
        }
2395
2396
0
        GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2397
0
        void *pProgressDataGlobal = psExtraArg->pProgressData;
2398
2399
0
        CPLErr eErr = CE_None;
2400
0
        if (nOKBands > 0)
2401
0
        {
2402
0
            if (nOKBands < nBandCount)
2403
0
            {
2404
0
                psExtraArg->pfnProgress = GDALScaledProgress;
2405
0
                psExtraArg->pProgressData = GDALCreateScaledProgress(
2406
0
                    0.0, static_cast<double>(nOKBands) / nBandCount,
2407
0
                    pfnProgressGlobal, pProgressDataGlobal);
2408
0
                if (psExtraArg->pProgressData == nullptr)
2409
0
                    psExtraArg->pfnProgress = nullptr;
2410
0
            }
2411
2412
0
            eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2413
0
                                     pData, nBufXSize, nBufYSize, eBufType,
2414
0
                                     nOKBands, panBandMap, nPixelSpace,
2415
0
                                     nLineSpace, nBandSpace, psExtraArg);
2416
2417
0
            if (nOKBands < nBandCount)
2418
0
            {
2419
0
                GDALDestroyScaledProgress(psExtraArg->pProgressData);
2420
0
            }
2421
0
        }
2422
0
        if (eErr == CE_None && nOKBands < nBandCount)
2423
0
        {
2424
0
            if (nOKBands > 0)
2425
0
            {
2426
0
                psExtraArg->pfnProgress = GDALScaledProgress;
2427
0
                psExtraArg->pProgressData = GDALCreateScaledProgress(
2428
0
                    static_cast<double>(nOKBands) / nBandCount, 1.0,
2429
0
                    pfnProgressGlobal, pProgressDataGlobal);
2430
0
                if (psExtraArg->pProgressData == nullptr)
2431
0
                    psExtraArg->pfnProgress = nullptr;
2432
0
            }
2433
0
            eErr = BandBasedRasterIO(
2434
0
                eRWFlag, nXOff, nYOff, nXSize, nYSize,
2435
0
                static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2436
0
                nBufYSize, eBufType, nBandCount - nOKBands,
2437
0
                panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2438
0
                psExtraArg);
2439
0
            if (nOKBands > 0)
2440
0
            {
2441
0
                GDALDestroyScaledProgress(psExtraArg->pProgressData);
2442
0
            }
2443
0
        }
2444
2445
0
        psExtraArg->pfnProgress = pfnProgressGlobal;
2446
0
        psExtraArg->pProgressData = pProgressDataGlobal;
2447
2448
0
        return eErr;
2449
0
    }
2450
2451
0
    return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2452
0
                             nBufXSize, nBufYSize, eBufType, nBandCount,
2453
0
                             panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2454
0
                             psExtraArg);
2455
0
}
2456
2457
//! @endcond
2458
2459
/************************************************************************/
2460
/*                         BandBasedRasterIO()                          */
2461
/*                                                                      */
2462
/*      Pass the request off to each band objects rasterio methods with */
2463
/*      appropriate arguments.                                          */
2464
/************************************************************************/
2465
2466
//! @cond Doxygen_Suppress
2467
CPLErr GDALDataset::BandBasedRasterIO(
2468
    GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
2469
    void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
2470
    int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
2471
    GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
2472
2473
0
{
2474
0
    int iBandIndex;
2475
0
    CPLErr eErr = CE_None;
2476
2477
0
    GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2478
0
    void *pProgressDataGlobal = psExtraArg->pProgressData;
2479
2480
0
    for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2481
0
         ++iBandIndex)
2482
0
    {
2483
0
        GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2484
2485
0
        if (poBand == nullptr)
2486
0
        {
2487
0
            eErr = CE_Failure;
2488
0
            break;
2489
0
        }
2490
2491
0
        GByte *pabyBandData =
2492
0
            static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2493
2494
0
        if (nBandCount > 1)
2495
0
        {
2496
0
            psExtraArg->pfnProgress = GDALScaledProgress;
2497
0
            psExtraArg->pProgressData = GDALCreateScaledProgress(
2498
0
                1.0 * iBandIndex / nBandCount,
2499
0
                1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2500
0
                pProgressDataGlobal);
2501
0
            if (psExtraArg->pProgressData == nullptr)
2502
0
                psExtraArg->pfnProgress = nullptr;
2503
0
        }
2504
2505
0
        eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2506
0
                                 pabyBandData, nBufXSize, nBufYSize, eBufType,
2507
0
                                 nPixelSpace, nLineSpace, psExtraArg);
2508
2509
0
        if (nBandCount > 1)
2510
0
            GDALDestroyScaledProgress(psExtraArg->pProgressData);
2511
0
    }
2512
2513
0
    psExtraArg->pfnProgress = pfnProgressGlobal;
2514
0
    psExtraArg->pProgressData = pProgressDataGlobal;
2515
2516
0
    return eErr;
2517
0
}
2518
2519
//! @endcond
2520
2521
/************************************************************************/
2522
/*               ValidateRasterIOOrAdviseReadParameters()               */
2523
/************************************************************************/
2524
2525
//! @cond Doxygen_Suppress
2526
CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2527
    const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
2528
    int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
2529
    int nBandCount, const int *panBandMap)
2530
0
{
2531
2532
    /* -------------------------------------------------------------------- */
2533
    /*      Some size values are "noop".  Lets just return to avoid         */
2534
    /*      stressing lower level functions.                                */
2535
    /* -------------------------------------------------------------------- */
2536
0
    if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2537
0
    {
2538
0
        CPLDebug("GDAL",
2539
0
                 "%s skipped for odd window or buffer size.\n"
2540
0
                 "  Window = (%d,%d)x%dx%d\n"
2541
0
                 "  Buffer = %dx%d",
2542
0
                 pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2543
0
                 nBufYSize);
2544
2545
0
        *pbStopProcessingOnCENone = TRUE;
2546
0
        return CE_None;
2547
0
    }
2548
2549
0
    CPLErr eErr = CE_None;
2550
0
    *pbStopProcessingOnCENone = FALSE;
2551
2552
0
    if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2553
0
        nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2554
0
        nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2555
0
    {
2556
0
        ReportError(CE_Failure, CPLE_IllegalArg,
2557
0
                    "Access window out of range in %s.  Requested "
2558
0
                    "(%d,%d) of size %dx%d on raster of %dx%d.",
2559
0
                    pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2560
0
                    nRasterYSize);
2561
0
        eErr = CE_Failure;
2562
0
    }
2563
2564
0
    if (panBandMap == nullptr && nBandCount > GetRasterCount())
2565
0
    {
2566
0
        ReportError(CE_Failure, CPLE_IllegalArg,
2567
0
                    "%s: nBandCount cannot be greater than %d", pszCallingFunc,
2568
0
                    GetRasterCount());
2569
0
        eErr = CE_Failure;
2570
0
    }
2571
2572
0
    for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2573
0
    {
2574
0
        int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2575
0
        if (iBand < 1 || iBand > GetRasterCount())
2576
0
        {
2577
0
            ReportError(
2578
0
                CE_Failure, CPLE_IllegalArg,
2579
0
                "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2580
0
                pszCallingFunc, i, iBand);
2581
0
            eErr = CE_Failure;
2582
0
        }
2583
2584
0
        if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
2585
0
        {
2586
0
            ReportError(
2587
0
                CE_Failure, CPLE_IllegalArg,
2588
0
                "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2589
0
                pszCallingFunc, i, iBand);
2590
0
            eErr = CE_Failure;
2591
0
        }
2592
0
    }
2593
2594
0
    return eErr;
2595
0
}
2596
2597
//! @endcond
2598
2599
/************************************************************************/
2600
/*                              RasterIO()                              */
2601
/************************************************************************/
2602
2603
/**
2604
 * \brief Read/write a region of image data from multiple bands.
2605
 *
2606
 * This method allows reading a region of one or more GDALRasterBands from
2607
 * this dataset into a buffer,  or writing data from a buffer into a region
2608
 * of the GDALRasterBands.  It automatically takes care of data type
2609
 * translation if the data type (eBufType) of the buffer is different than
2610
 * that of the GDALRasterBand.
2611
 * The method also takes care of image decimation / replication if the
2612
 * buffer size (nBufXSize x nBufYSize) is different than the size of the
2613
 * region being accessed (nXSize x nYSize).
2614
 *
2615
 * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be
2616
 * fully within the raster space, that is nXOff >= 0, nYOff >= 0,
2617
 * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().
2618
 * If reads larger than the raster space are wished, GDALTranslate() might be used.
2619
 * Or use nLineSpace and a possibly shifted pData value.
2620
 *
2621
 * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2622
 * writing from various organization of buffers.
2623
 *
2624
 * Some formats may efficiently implement decimation into a buffer by
2625
 * reading from lower resolution overview images. The logic of the default
2626
 * implementation in the base class GDALRasterBand is the following one. It
2627
 * computes a target_downscaling_factor from the window of interest and buffer
2628
 * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
2629
 * It then walks through overviews and will select the first one whose
2630
 * downscaling factor is greater than target_downscaling_factor / 1.2.
2631
 *
2632
 * Let's assume we have overviews at downscaling factors 2, 4 and 8.
2633
 * The relationship between target_downscaling_factor and the select overview
2634
 * level is the following one:
2635
 *
2636
 * target_downscaling_factor  | selected_overview
2637
 * -------------------------  | -----------------
2638
 * ]0,       2 / 1.2]         | full resolution band
2639
 * ]2 / 1.2, 4 / 1.2]         | 2x downsampled band
2640
 * ]4 / 1.2, 8 / 1.2]         | 4x downsampled band
2641
 * ]8 / 1.2, infinity[        | 8x downsampled band
2642
 *
2643
 * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
2644
 * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
2645
 * option. Also note that starting with GDAL 3.9, when the resampling algorithm
2646
 * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
2647
 * this oversampling threshold defaults to 1. Consequently if there are overviews
2648
 * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
2649
 * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
2650
 *
2651
 * For highest performance full resolution data access, read and write
2652
 * on "block boundaries" as returned by GetBlockSize(), or use the
2653
 * ReadBlock() and WriteBlock() methods.
2654
 *
2655
 * This method is the same as the C GDALDatasetRasterIO() or
2656
 * GDALDatasetRasterIOEx() functions.
2657
 *
2658
 * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2659
 * write a region of data.
2660
 *
2661
 * @param nXOff The pixel offset to the top left corner of the region
2662
 * of the band to be accessed.  This would be zero to start from the left side.
2663
 *
2664
 * @param nYOff The line offset to the top left corner of the region
2665
 * of the band to be accessed.  This would be zero to start from the top.
2666
 *
2667
 * @param nXSize The width of the region of the band to be accessed in pixels.
2668
 *
2669
 * @param nYSize The height of the region of the band to be accessed in lines.
2670
 *
2671
 * @param pData The buffer into which the data should be read, or from which
2672
 * it should be written.  This buffer must contain at least
2673
 * nBufXSize * nBufYSize * nBandCount words of type eBufType.  It is organized
2674
 * in left to right,top to bottom pixel order.  Spacing is controlled by the
2675
 * nPixelSpace, and nLineSpace parameters.
2676
 * Note that even with eRWFlag==GF_Write, the content of the buffer might be
2677
 * temporarily modified during the execution of this method (and eventually
2678
 * restored back to its original content), so it is not safe to use a buffer
2679
 * stored in a read-only section of the calling program.
2680
 *
2681
 * @param nBufXSize the width of the buffer image into which the desired region
2682
 * is to be read, or from which it is to be written.
2683
 *
2684
 * @param nBufYSize the height of the buffer image into which the desired
2685
 * region is to be read, or from which it is to be written.
2686
 *
2687
 * @param eBufType the type of the pixel values in the pData data buffer. The
2688
 * pixel values will automatically be translated to/from the GDALRasterBand
2689
 * data type as needed. Most driver implementations will use GDALCopyWords64()
2690
 * to perform data type translation.
2691
 *
2692
 * @param nBandCount the number of bands being read or written.
2693
 *
2694
 * @param panBandMap the list of nBandCount band numbers being read/written.
2695
 * Note band numbers are 1 based. This may be NULL to select the first
2696
 * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and
2697
 * not "const int*")
2698
 *
2699
 * @param nPixelSpace The byte offset from the start of one pixel value in
2700
 * pData to the start of the next pixel value within a scanline. If defaulted
2701
 * (0) the size of the datatype eBufType is used.
2702
 *
2703
 * @param nLineSpace The byte offset from the start of one scanline in
2704
 * pData to the start of the next. If defaulted (0) the size of the datatype
2705
 * eBufType * nBufXSize is used.
2706
 *
2707
 * @param nBandSpace the byte offset from the start of one bands data to the
2708
 * start of the next. If defaulted (0) the value will be
2709
 * nLineSpace * nBufYSize implying band sequential organization
2710
 * of the data buffer.
2711
 *
2712
 * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
2713
 * structure with additional arguments to specify resampling and progress
2714
 * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
2715
 * configuration option can also be defined to override the default resampling
2716
 * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
2717
 *
2718
 * @return CE_Failure if the access fails, otherwise CE_None.
2719
 */
2720
2721
CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2722
                             int nXSize, int nYSize, void *pData, int nBufXSize,
2723
                             int nBufYSize, GDALDataType eBufType,
2724
                             int nBandCount, const int *panBandMap,
2725
                             GSpacing nPixelSpace, GSpacing nLineSpace,
2726
                             GSpacing nBandSpace,
2727
                             GDALRasterIOExtraArg *psExtraArg)
2728
2729
0
{
2730
0
    GDALRasterIOExtraArg sExtraArg;
2731
0
    if (psExtraArg == nullptr)
2732
0
    {
2733
0
        INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2734
2735
        // 4 below inits are not strictly needed but make Coverity Scan
2736
        // happy
2737
0
        sExtraArg.dfXOff = nXOff;
2738
0
        sExtraArg.dfYOff = nYOff;
2739
0
        sExtraArg.dfXSize = nXSize;
2740
0
        sExtraArg.dfYSize = nYSize;
2741
2742
0
        psExtraArg = &sExtraArg;
2743
0
    }
2744
0
    else if (CPL_UNLIKELY(psExtraArg->nVersion >
2745
0
                          RASTERIO_EXTRA_ARG_CURRENT_VERSION))
2746
0
    {
2747
0
        ReportError(CE_Failure, CPLE_AppDefined,
2748
0
                    "Unhandled version of GDALRasterIOExtraArg");
2749
0
        return CE_Failure;
2750
0
    }
2751
2752
0
    GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2753
0
                                       nBufYSize);
2754
2755
0
    if (CPL_UNLIKELY(nullptr == pData))
2756
0
    {
2757
0
        ReportError(CE_Failure, CPLE_AppDefined,
2758
0
                    "The buffer into which the data should be read is null");
2759
0
        return CE_Failure;
2760
0
    }
2761
2762
    /* -------------------------------------------------------------------- */
2763
    /*      Do some validation of parameters.                               */
2764
    /* -------------------------------------------------------------------- */
2765
2766
0
    if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))
2767
0
    {
2768
0
        ReportError(
2769
0
            CE_Failure, CPLE_IllegalArg,
2770
0
            "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
2771
0
            eRWFlag);
2772
0
        return CE_Failure;
2773
0
    }
2774
2775
0
    if (eRWFlag == GF_Write)
2776
0
    {
2777
0
        if (CPL_UNLIKELY(eAccess != GA_Update))
2778
0
        {
2779
0
            ReportError(CE_Failure, CPLE_AppDefined,
2780
0
                        "Write operation not permitted on dataset opened "
2781
0
                        "in read-only mode");
2782
0
            return CE_Failure;
2783
0
        }
2784
0
    }
2785
2786
0
    int bStopProcessing = FALSE;
2787
0
    CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2788
0
        "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2789
0
        nBufYSize, nBandCount, panBandMap);
2790
0
    if (eErr != CE_None || bStopProcessing)
2791
0
        return eErr;
2792
0
    if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))
2793
0
    {
2794
0
        ReportError(CE_Failure, CPLE_AppDefined,
2795
0
                    "Illegal GDT_Unknown/GDT_TypeCount argument");
2796
0
        return CE_Failure;
2797
0
    }
2798
2799
    /* -------------------------------------------------------------------- */
2800
    /*      If pixel and line spacing are defaulted assign reasonable      */
2801
    /*      value assuming a packed buffer.                                 */
2802
    /* -------------------------------------------------------------------- */
2803
0
    if (nPixelSpace == 0)
2804
0
        nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2805
2806
0
    if (nLineSpace == 0)
2807
0
    {
2808
0
        nLineSpace = nPixelSpace * nBufXSize;
2809
0
    }
2810
2811
0
    if (nBandSpace == 0 && nBandCount > 1)
2812
0
    {
2813
0
        nBandSpace = nLineSpace * nBufYSize;
2814
0
    }
2815
2816
0
    if (panBandMap == nullptr)
2817
0
    {
2818
0
        if (!m_poPrivate)
2819
0
            return CE_Failure;
2820
0
        CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
2821
0
        panBandMap = m_poPrivate->m_anBandMap.data();
2822
0
    }
2823
2824
0
    int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2825
2826
    /* -------------------------------------------------------------------- */
2827
    /*      We are being forced to use cached IO instead of a driver        */
2828
    /*      specific implementation.                                        */
2829
    /* -------------------------------------------------------------------- */
2830
0
    if (bForceCachedIO)
2831
0
    {
2832
0
        eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2833
0
                                  nBufXSize, nBufYSize, eBufType, nBandCount,
2834
0
                                  panBandMap, nPixelSpace, nLineSpace,
2835
0
                                  nBandSpace, psExtraArg);
2836
0
    }
2837
2838
    /* -------------------------------------------------------------------- */
2839
    /*      Call the format specific function.                              */
2840
    /* -------------------------------------------------------------------- */
2841
0
    else
2842
0
    {
2843
0
        eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2844
0
                         nBufXSize, nBufYSize, eBufType, nBandCount,
2845
                         // TODO: remove this const_cast once IRasterIO()
2846
                         // takes a const int*
2847
0
                         const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,
2848
0
                         nBandSpace, psExtraArg);
2849
0
    }
2850
2851
0
    if (bCallLeaveReadWrite)
2852
0
        LeaveReadWrite();
2853
2854
0
    return eErr;
2855
0
}
2856
2857
/************************************************************************/
2858
/*                        GDALDatasetRasterIO()                         */
2859
/************************************************************************/
2860
2861
/**
2862
 * \brief Read/write a region of image data from multiple bands.
2863
 *
2864
 * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
2865
 * resolution, progress callback, etc. are needed)
2866
 *
2867
 * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
2868
 *
2869
 * @see GDALDataset::RasterIO()
2870
 */
2871
2872
CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
2873
                                       int nXOff, int nYOff, int nXSize,
2874
                                       int nYSize, void *pData, int nBufXSize,
2875
                                       int nBufYSize, GDALDataType eBufType,
2876
                                       int nBandCount, const int *panBandMap,
2877
                                       int nPixelSpace, int nLineSpace,
2878
                                       int nBandSpace)
2879
2880
0
{
2881
0
    VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
2882
2883
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2884
2885
0
    return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2886
0
                          nBufXSize, nBufYSize, eBufType, nBandCount,
2887
0
                          panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2888
0
                          nullptr);
2889
0
}
2890
2891
/************************************************************************/
2892
/*                       GDALDatasetRasterIOEx()                        */
2893
/************************************************************************/
2894
2895
/**
2896
 * \brief Read/write a region of image data from multiple bands.
2897
 *
2898
 * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
2899
 *
2900
 * @see GDALDataset::RasterIO()
2901
 * @since GDAL 2.0
2902
 */
2903
2904
CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
2905
    GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
2906
    int nYSize, void *pData, int nBufXSize, int nBufYSize,
2907
    GDALDataType eBufType, int nBandCount, const int *panBandMap,
2908
    GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
2909
    GDALRasterIOExtraArg *psExtraArg)
2910
2911
0
{
2912
0
    VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
2913
2914
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2915
2916
0
    return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2917
0
                          nBufXSize, nBufYSize, eBufType, nBandCount,
2918
0
                          panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2919
0
                          psExtraArg);
2920
0
}
2921
2922
/************************************************************************/
2923
/*                          GetOpenDatasets()                           */
2924
/************************************************************************/
2925
2926
/**
2927
 * \brief Fetch all open GDAL dataset handles.
2928
 *
2929
 * This method is the same as the C function GDALGetOpenDatasets().
2930
 *
2931
 * NOTE: This method is not thread safe.  The returned list may change
2932
 * at any time and it should not be freed.
2933
 *
2934
 * @param pnCount integer into which to place the count of dataset pointers
2935
 * being returned.
2936
 *
2937
 * @return a pointer to an array of dataset handles.
2938
 */
2939
2940
GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
2941
2942
0
{
2943
0
    CPLMutexHolderD(&hDLMutex);
2944
2945
0
    if (poAllDatasetMap == nullptr)
2946
0
    {
2947
0
        *pnCount = 0;
2948
0
        return nullptr;
2949
0
    }
2950
2951
0
    *pnCount = static_cast<int>(poAllDatasetMap->size());
2952
0
    ppDatasets = static_cast<GDALDataset **>(
2953
0
        CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
2954
0
    std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
2955
0
    for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
2956
0
        ppDatasets[i] = oIter->first;
2957
0
    return ppDatasets;
2958
0
}
2959
2960
/************************************************************************/
2961
/*                        GDALGetOpenDatasets()                         */
2962
/************************************************************************/
2963
2964
/**
2965
 * \brief Fetch all open GDAL dataset handles.
2966
 *
2967
 * @see GDALDataset::GetOpenDatasets()
2968
 */
2969
2970
void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
2971
2972
0
{
2973
0
    VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
2974
0
    VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
2975
2976
0
    *ppahDSList =
2977
0
        reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
2978
0
}
2979
2980
/************************************************************************/
2981
/*                        GDALCleanOpenDatasetsList()                   */
2982
/************************************************************************/
2983
2984
// Useful when called from the child of a fork(), to avoid closing
2985
// the datasets of the parent at the child termination.
2986
void GDALNullifyOpenDatasetsList()
2987
0
{
2988
0
    poAllDatasetMap = nullptr;
2989
0
    phSharedDatasetSet = nullptr;
2990
0
    ppDatasets = nullptr;
2991
0
    hDLMutex = nullptr;
2992
0
}
2993
2994
/************************************************************************/
2995
/*                             GDALGetAccess()                          */
2996
/************************************************************************/
2997
2998
/**
2999
 * \brief Return access flag
3000
 *
3001
 * @see GDALDataset::GetAccess()
3002
 */
3003
3004
int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
3005
0
{
3006
0
    VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
3007
3008
0
    return GDALDataset::FromHandle(hDS)->GetAccess();
3009
0
}
3010
3011
/************************************************************************/
3012
/*                             AdviseRead()                             */
3013
/************************************************************************/
3014
3015
/**
3016
 * \brief Advise driver of upcoming read requests.
3017
 *
3018
 * Some GDAL drivers operate more efficiently if they know in advance what
3019
 * set of upcoming read requests will be made.  The AdviseRead() method allows
3020
 * an application to notify the driver of the region and bands of interest,
3021
 * and at what resolution the region will be read.
3022
 *
3023
 * Many drivers just ignore the AdviseRead() call, but it can dramatically
3024
 * accelerate access via some drivers.
3025
 *
3026
 * Depending on call paths, drivers might receive several calls to
3027
 * AdviseRead() with the same parameters.
3028
 *
3029
 * @param nXOff The pixel offset to the top left corner of the region
3030
 * of the band to be accessed.  This would be zero to start from the left side.
3031
 *
3032
 * @param nYOff The line offset to the top left corner of the region
3033
 * of the band to be accessed.  This would be zero to start from the top.
3034
 *
3035
 * @param nXSize The width of the region of the band to be accessed in pixels.
3036
 *
3037
 * @param nYSize The height of the region of the band to be accessed in lines.
3038
 *
3039
 * @param nBufXSize the width of the buffer image into which the desired region
3040
 * is to be read, or from which it is to be written.
3041
 *
3042
 * @param nBufYSize the height of the buffer image into which the desired
3043
 * region is to be read, or from which it is to be written.
3044
 *
3045
 * @param eBufType the type of the pixel values in the pData data buffer.  The
3046
 * pixel values will automatically be translated to/from the GDALRasterBand
3047
 * data type as needed.
3048
 *
3049
 * @param nBandCount the number of bands being read or written.
3050
 *
3051
 * @param panBandMap the list of nBandCount band numbers being read/written.
3052
 * Note band numbers are 1 based.   This may be NULL to select the first
3053
 * nBandCount bands.
3054
 *
3055
 * @param papszOptions a list of name=value strings with special control
3056
 * options.  Normally this is NULL.
3057
 *
3058
 * @return CE_Failure if the request is invalid and CE_None if it works or
3059
 * is ignored.
3060
 */
3061
3062
CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
3063
                               int nBufXSize, int nBufYSize,
3064
                               GDALDataType eBufType, int nBandCount,
3065
                               int *panBandMap, char **papszOptions)
3066
3067
0
{
3068
    /* -------------------------------------------------------------------- */
3069
    /*      Do some validation of parameters.                               */
3070
    /* -------------------------------------------------------------------- */
3071
0
    int bStopProcessing = FALSE;
3072
0
    CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3073
0
        "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3074
0
        nBufXSize, nBufYSize, nBandCount, panBandMap);
3075
0
    if (eErr != CE_None || bStopProcessing)
3076
0
        return eErr;
3077
3078
0
    for (int iBand = 0; iBand < nBandCount; ++iBand)
3079
0
    {
3080
0
        GDALRasterBand *poBand = nullptr;
3081
3082
0
        if (panBandMap == nullptr)
3083
0
            poBand = GetRasterBand(iBand + 1);
3084
0
        else
3085
0
            poBand = GetRasterBand(panBandMap[iBand]);
3086
3087
0
        if (poBand == nullptr)
3088
0
            return CE_Failure;
3089
3090
0
        eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3091
0
                                  nBufYSize, eBufType, papszOptions);
3092
3093
0
        if (eErr != CE_None)
3094
0
            return eErr;
3095
0
    }
3096
3097
0
    return CE_None;
3098
0
}
3099
3100
/************************************************************************/
3101
/*                       GDALDatasetAdviseRead()                        */
3102
/************************************************************************/
3103
3104
/**
3105
 * \brief Advise driver of upcoming read requests.
3106
 *
3107
 * @see GDALDataset::AdviseRead()
3108
 */
3109
CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
3110
                                         int nXSize, int nYSize, int nBufXSize,
3111
                                         int nBufYSize, GDALDataType eDT,
3112
                                         int nBandCount, int *panBandMap,
3113
                                         CSLConstList papszOptions)
3114
3115
0
{
3116
0
    VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
3117
3118
0
    return GDALDataset::FromHandle(hDS)->AdviseRead(
3119
0
        nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
3120
0
        panBandMap, const_cast<char **>(papszOptions));
3121
0
}
3122
3123
/************************************************************************/
3124
/*                         GDALAntiRecursionStruct                      */
3125
/************************************************************************/
3126
3127
// Prevent infinite recursion.
3128
struct GDALAntiRecursionStruct
3129
{
3130
    struct DatasetContext
3131
    {
3132
        std::string osFilename;
3133
        int nOpenFlags;
3134
        std::string osAllowedDrivers;
3135
3136
        DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3137
                       const std::string &osAllowedDriversIn)
3138
0
            : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3139
0
              osAllowedDrivers(osAllowedDriversIn)
3140
0
        {
3141
0
        }
3142
    };
3143
3144
    struct DatasetContextCompare
3145
    {
3146
        bool operator()(const DatasetContext &lhs,
3147
                        const DatasetContext &rhs) const
3148
0
        {
3149
0
            return lhs.osFilename < rhs.osFilename ||
3150
0
                   (lhs.osFilename == rhs.osFilename &&
3151
0
                    (lhs.nOpenFlags < rhs.nOpenFlags ||
3152
0
                     (lhs.nOpenFlags == rhs.nOpenFlags &&
3153
0
                      lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
3154
0
        }
3155
    };
3156
3157
    std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
3158
    int nRecLevel = 0;
3159
    std::map<std::string, int> m_oMapDepth{};
3160
};
3161
3162
#ifdef _WIN32
3163
// Currently thread_local and C++ objects don't work well with DLL on Windows
3164
static void FreeAntiRecursionOpen(void *pData)
3165
{
3166
    delete static_cast<GDALAntiRecursionStruct *>(pData);
3167
}
3168
3169
static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3170
{
3171
    static GDALAntiRecursionStruct dummy;
3172
    int bMemoryErrorOccurred = false;
3173
    void *pData =
3174
        CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
3175
    if (bMemoryErrorOccurred)
3176
    {
3177
        return dummy;
3178
    }
3179
    if (pData == nullptr)
3180
    {
3181
        auto pAntiRecursion = new GDALAntiRecursionStruct();
3182
        CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
3183
                                FreeAntiRecursionOpen, &bMemoryErrorOccurred);
3184
        if (bMemoryErrorOccurred)
3185
        {
3186
            delete pAntiRecursion;
3187
            return dummy;
3188
        }
3189
        return *pAntiRecursion;
3190
    }
3191
    return *static_cast<GDALAntiRecursionStruct *>(pData);
3192
}
3193
#else
3194
static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
3195
3196
static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3197
0
{
3198
0
    return g_tls_antiRecursion;
3199
0
}
3200
#endif
3201
3202
//! @cond Doxygen_Suppress
3203
GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3204
0
    : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3205
0
      m_osIdentifier(osIdentifier),
3206
0
      m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3207
0
{
3208
0
    CPLAssert(!osIdentifier.empty());
3209
0
}
3210
3211
GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3212
    const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3213
0
    : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3214
0
      m_osIdentifier(osIdentifier.empty()
3215
0
                         ? osIdentifier
3216
0
                         : other.m_osIdentifier + osIdentifier),
3217
0
      m_nDepth(m_osIdentifier.empty()
3218
0
                   ? 0
3219
0
                   : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3220
0
{
3221
0
}
3222
3223
GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3224
0
{
3225
0
    if (!m_osIdentifier.empty())
3226
0
    {
3227
0
        --m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier];
3228
0
    }
3229
0
}
3230
3231
//! @endcond
3232
3233
/************************************************************************/
3234
/*                            GetFileList()                             */
3235
/************************************************************************/
3236
3237
/**
3238
 * \brief Fetch files forming dataset.
3239
 *
3240
 * Returns a list of files believed to be part of this dataset.  If it returns
3241
 * an empty list of files it means there is believed to be no local file
3242
 * system files associated with the dataset (for instance a virtual dataset).
3243
 * The returned file list is owned by the caller and should be deallocated
3244
 * with CSLDestroy().
3245
 *
3246
 * The returned filenames will normally be relative or absolute paths
3247
 * depending on the path used to originally open the dataset.  The strings
3248
 * will be UTF-8 encoded.
3249
 *
3250
 * This method is the same as the C GDALGetFileList() function.
3251
 *
3252
 * @return NULL or a NULL terminated array of file names.
3253
 */
3254
3255
char **GDALDataset::GetFileList()
3256
3257
0
{
3258
0
    CPLString osMainFilename = GetDescription();
3259
0
    VSIStatBufL sStat;
3260
3261
0
    GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3262
0
    GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3263
0
                                                        std::string());
3264
0
    auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3265
0
    if (cpl::contains(aosDatasetList, datasetCtxt))
3266
0
        return nullptr;
3267
3268
    /* -------------------------------------------------------------------- */
3269
    /*      Is the main filename even a real filesystem object?             */
3270
    /* -------------------------------------------------------------------- */
3271
0
    int bMainFileReal =
3272
0
        VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3273
3274
    /* -------------------------------------------------------------------- */
3275
    /*      Form new list.                                                  */
3276
    /* -------------------------------------------------------------------- */
3277
0
    char **papszList = nullptr;
3278
3279
0
    if (bMainFileReal)
3280
0
        papszList = CSLAddString(papszList, osMainFilename);
3281
3282
0
    if (sAntiRecursion.nRecLevel == 100)
3283
0
    {
3284
0
        CPLError(CE_Failure, CPLE_AppDefined,
3285
0
                 "GetFileList() called with too many recursion levels");
3286
0
        return papszList;
3287
0
    }
3288
0
    ++sAntiRecursion.nRecLevel;
3289
3290
    /* -------------------------------------------------------------------- */
3291
    /*      Do we have a known overview file?                               */
3292
    /* -------------------------------------------------------------------- */
3293
0
    if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3294
0
    {
3295
0
        auto iter = aosDatasetList.insert(datasetCtxt).first;
3296
0
        char **papszOvrList = oOvManager.poODS->GetFileList();
3297
0
        papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3298
0
        CSLDestroy(papszOvrList);
3299
0
        aosDatasetList.erase(iter);
3300
0
    }
3301
3302
    /* -------------------------------------------------------------------- */
3303
    /*      Do we have a known mask file?                                   */
3304
    /* -------------------------------------------------------------------- */
3305
0
    if (oOvManager.HaveMaskFile())
3306
0
    {
3307
0
        auto iter = aosDatasetList.insert(std::move(datasetCtxt)).first;
3308
0
        for (const char *pszFile :
3309
0
             CPLStringList(oOvManager.poMaskDS->GetFileList()))
3310
0
        {
3311
0
            if (CSLFindString(papszList, pszFile) < 0)
3312
0
                papszList = CSLAddString(papszList, pszFile);
3313
0
        }
3314
0
        aosDatasetList.erase(iter);
3315
0
    }
3316
3317
0
    --sAntiRecursion.nRecLevel;
3318
3319
0
    return papszList;
3320
0
}
3321
3322
/************************************************************************/
3323
/*                          GDALGetFileList()                           */
3324
/************************************************************************/
3325
3326
/**
3327
 * \brief Fetch files forming dataset.
3328
 *
3329
 * @see GDALDataset::GetFileList()
3330
 */
3331
3332
char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3333
3334
0
{
3335
0
    VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3336
3337
0
    return GDALDataset::FromHandle(hDS)->GetFileList();
3338
0
}
3339
3340
/************************************************************************/
3341
/*                           CreateMaskBand()                           */
3342
/************************************************************************/
3343
3344
/**
3345
 * \brief Adds a mask band to the dataset
3346
 *
3347
 * The default implementation of the CreateMaskBand() method is implemented
3348
 * based on similar rules to the .ovr handling implemented using the
3349
 * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3350
 * be created with the same basename as the original file, and it will have
3351
 * one band.
3352
 * The mask images will be deflate compressed tiled images with the same
3353
 * block size as the original image if possible.
3354
 * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3355
 * level, where xx matches the band number of a band of the main dataset. The
3356
 * value of those items will be the one of the nFlagsIn parameter.
3357
 *
3358
 * Note that if you got a mask band with a previous call to GetMaskBand(), it
3359
 * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3360
 * again.
3361
 *
3362
 * @since GDAL 1.5.0
3363
 *
3364
 * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3365
 *                 GMF_PER_DATASET will be always set, even if not explicitly
3366
 *                 specified.
3367
 * @return CE_None on success or CE_Failure on an error.
3368
 *
3369
 * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3370
 * @see GDALRasterBand::CreateMaskBand()
3371
 *
3372
 */
3373
CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
3374
3375
0
{
3376
0
    if (oOvManager.IsInitialized())
3377
0
    {
3378
0
        CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3379
0
        if (eErr != CE_None)
3380
0
            return eErr;
3381
3382
        // Invalidate existing raster band masks.
3383
0
        for (int i = 0; i < nBands; ++i)
3384
0
        {
3385
0
            GDALRasterBand *poBand = papoBands[i];
3386
0
            poBand->poMask.reset();
3387
0
        }
3388
3389
0
        return CE_None;
3390
0
    }
3391
3392
0
    ReportError(CE_Failure, CPLE_NotSupported,
3393
0
                "CreateMaskBand() not supported for this dataset.");
3394
3395
0
    return CE_Failure;
3396
0
}
3397
3398
/************************************************************************/
3399
/*                     GDALCreateDatasetMaskBand()                      */
3400
/************************************************************************/
3401
3402
/**
3403
 * \brief Adds a mask band to the dataset
3404
 * @see GDALDataset::CreateMaskBand()
3405
 */
3406
CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3407
3408
0
{
3409
0
    VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3410
3411
0
    return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3412
0
}
3413
3414
/************************************************************************/
3415
/*                              GDALOpen()                              */
3416
/************************************************************************/
3417
3418
/**
3419
 * \brief Open a raster file as a GDALDataset.
3420
 *
3421
 * This function will try to open the passed file, or virtual dataset
3422
 * name by invoking the Open method of each registered GDALDriver in turn.
3423
 * The first successful open will result in a returned dataset.  If all
3424
 * drivers fail then NULL is returned and an error is issued.
3425
 *
3426
 * Several recommendations :
3427
 * <ul>
3428
 * <li>If you open a dataset object with GA_Update access, it is not recommended
3429
 * to open a new dataset on the same underlying file.</li>
3430
 * <li>The returned dataset should only be accessed by one thread at a time. If
3431
 * you want to use it from different threads, you must add all necessary code
3432
 * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
3433
 * as GeoTIFF, maintain internal state variables that are updated each time a
3434
 * new block is read, thus preventing concurrent use.) </li>
3435
 * </ul>
3436
 *
3437
 * For drivers supporting the VSI virtual file API, it is possible to open a
3438
 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3439
 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3440
 * server (see VSIInstallCurlFileHandler())
3441
 *
3442
 * \sa GDALOpenShared()
3443
 * \sa GDALOpenEx()
3444
 *
3445
 * @param pszFilename the name of the file to access.  In the case of
3446
 * exotic drivers this may not refer to a physical file, but instead contain
3447
 * information for the driver on how to access a dataset.  It should be in UTF-8
3448
 * encoding.
3449
 *
3450
 * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
3451
 * drivers support only read only access.
3452
 *
3453
 * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
3454
 * this handle can be cast to a GDALDataset *.
3455
 */
3456
3457
GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3458
3459
0
{
3460
0
    const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3461
0
    const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3462
0
    GDALDatasetH hDataset =
3463
0
        GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3464
0
    return hDataset;
3465
0
}
3466
3467
/************************************************************************/
3468
/*                             GetSharedDS()                            */
3469
/************************************************************************/
3470
3471
static GDALDataset *GetSharedDS(const char *pszFilename,
3472
                                unsigned int nOpenFlags,
3473
                                const char *const *papszOpenOptions)
3474
0
{
3475
0
    CPLMutexHolderD(&hDLMutex);
3476
3477
0
    if (phSharedDatasetSet != nullptr)
3478
0
    {
3479
0
        const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3480
0
        SharedDatasetCtxt sStruct;
3481
3482
0
        sStruct.nPID = nThisPID;
3483
0
        sStruct.pszDescription = const_cast<char *>(pszFilename);
3484
0
        sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3485
0
        std::string osConcatenatedOpenOptions =
3486
0
            GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3487
0
        sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3488
0
        sStruct.poDS = nullptr;
3489
0
        SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3490
0
            CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3491
0
        if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3492
0
        {
3493
0
            sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3494
0
            psStruct = static_cast<SharedDatasetCtxt *>(
3495
0
                CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3496
0
        }
3497
0
        if (psStruct)
3498
0
        {
3499
0
            return psStruct->poDS;
3500
0
        }
3501
0
    }
3502
0
    return nullptr;
3503
0
}
3504
3505
/************************************************************************/
3506
/*                             GDALOpenEx()                             */
3507
/************************************************************************/
3508
3509
/**
3510
 * \brief Open a raster or vector file as a GDALDataset.
3511
 *
3512
 * This function will try to open the passed file, or virtual dataset
3513
 * name by invoking the Open method of each registered GDALDriver in turn.
3514
 * The first successful open will result in a returned dataset.  If all
3515
 * drivers fail then NULL is returned and an error is issued.
3516
 *
3517
 * Several recommendations :
3518
 * <ul>
3519
 * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3520
 * recommended to open a new dataset on the same underlying file.</li>
3521
 * <li>The returned dataset should only be accessed by one thread at a time. If
3522
 * you want to use it from different threads, you must add all necessary code
3523
 * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
3524
 * as GeoTIFF, maintain internal state variables that are updated each time a
3525
 * new block is read, thus preventing concurrent use.) </li>
3526
 * </ul>
3527
 *
3528
 * For drivers supporting the VSI virtual file API, it is possible to open a
3529
 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3530
 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3531
 * server (see VSIInstallCurlFileHandler())
3532
 *
3533
 * In order to reduce the need for searches through the operating system
3534
 * file system machinery, it is possible to give an optional list of files with
3535
 * the papszSiblingFiles parameter.
3536
 * This is the list of all files at the same level in the file system as the
3537
 * target file, including the target file. The filenames must not include any
3538
 * path components, are essentially just the output of VSIReadDir() on the
3539
 * parent directory. If the target object does not have filesystem semantics
3540
 * then the file list should be NULL.
3541
 *
3542
 * @param pszFilename the name of the file to access.  In the case of
3543
 * exotic drivers this may not refer to a physical file, but instead contain
3544
 * information for the driver on how to access a dataset.  It should be in UTF-8
3545
 * encoding.
3546
 *
3547
 * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3548
 * through logical or operator.
3549
 * <ul>
3550
 * <li>Driver kind:
3551
 *   <ul>
3552
 *     <li>GDAL_OF_RASTER for raster drivers,</li>
3553
 *     <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
3554
 *     <li>GDAL_OF_VECTOR for vector drivers,</li>
3555
 *     <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
3556
 *    </ul>
3557
 * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
3558
 * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
3559
 * | GDAL_OF_GNM is implied.
3560
 * </li>
3561
 * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.
3562
 * </li>
3563
 * <li>Shared mode: GDAL_OF_SHARED. If set,
3564
 * it allows the sharing of GDALDataset handles for a dataset with other callers
3565
 * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
3566
 * its list of currently open and shared GDALDataset's, and if the
3567
 * GetDescription() name for one exactly matches the pszFilename passed to
3568
 * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
3569
 * from the same thread.
3570
 * </li>
3571
 * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).
3572
 * This must be use in combination with GDAL_OF_RASTER, and is mutually
3573
 * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or
3574
 * GDAL_OF_GNM.
3575
 * </li>
3576
 * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
3577
 * a failed attempt to open the file will lead to an error message to be
3578
 * reported.
3579
 * </li>
3580
 * </ul>
3581
 *
3582
 * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3583
 * terminated list of strings with the driver short names that must be
3584
 * considered.
3585
 *
3586
 * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3587
 * options passed to candidate drivers. An option exists for all drivers,
3588
 * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3589
 * The level index starts at 0. The level number can be suffixed by "only" to
3590
 * specify that only this overview level must be visible, and not sub-levels.
3591
 * Open options are validated by default, and a warning is emitted in case the
3592
 * option is not recognized. In some scenarios, it might be not desirable (e.g.
3593
 * when not knowing which driver will open the file), so the special open option
3594
 * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3595
 * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3596
 * that it may not cause a warning if the driver doesn't declare this option.
3597
 * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3598
 * no overviews should be exposed.
3599
 *
3600
 * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3601
 * filenames that are auxiliary to the main filename. If NULL is passed, a
3602
 * probing of the file system will be done.
3603
 *
3604
 * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
3605
 * this handle can be cast to a GDALDataset *.
3606
 *
3607
 * @since GDAL 2.0
3608
 */
3609
3610
GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
3611
                                    unsigned int nOpenFlags,
3612
                                    const char *const *papszAllowedDrivers,
3613
                                    const char *const *papszOpenOptions,
3614
                                    const char *const *papszSiblingFiles)
3615
0
{
3616
0
    VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3617
3618
    // Hack for the ZARR driver. We translate the CACHE_KERCHUNK_JSON
3619
    // into VSIKERCHUNK_USE_CACHE config option
3620
0
    std::unique_ptr<CPLConfigOptionSetter> poVSIKERCHUNK_USE_CACHESetter;
3621
0
    if (CPLFetchBool(papszOpenOptions, "CACHE_KERCHUNK_JSON", false))
3622
0
    {
3623
0
        poVSIKERCHUNK_USE_CACHESetter = std::make_unique<CPLConfigOptionSetter>(
3624
0
            "VSIKERCHUNK_USE_CACHE", "YES", false);
3625
0
    }
3626
3627
    // Do some sanity checks on incompatible flags with thread-safe mode.
3628
0
    if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3629
0
    {
3630
0
        const struct
3631
0
        {
3632
0
            int nFlag;
3633
0
            const char *pszFlagName;
3634
0
        } asFlags[] = {
3635
0
            {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"},
3636
0
            {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"},
3637
0
            {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"},
3638
0
            {GDAL_OF_GNM, "GDAL_OF_GNM"},
3639
0
        };
3640
3641
0
        for (const auto &asFlag : asFlags)
3642
0
        {
3643
0
            if ((nOpenFlags & asFlag.nFlag) != 0)
3644
0
            {
3645
0
                CPLError(CE_Failure, CPLE_IllegalArg,
3646
0
                         "GDAL_OF_THREAD_SAFE and %s are mutually "
3647
0
                         "exclusive",
3648
0
                         asFlag.pszFlagName);
3649
0
                return nullptr;
3650
0
            }
3651
0
        }
3652
0
    }
3653
3654
    // If no driver kind is specified, assume all are to be probed.
3655
0
    if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3656
0
        nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3657
3658
    /* -------------------------------------------------------------------- */
3659
    /*      In case of shared dataset, first scan the existing list to see  */
3660
    /*      if it could already contain the requested dataset.              */
3661
    /* -------------------------------------------------------------------- */
3662
0
    if (nOpenFlags & GDAL_OF_SHARED)
3663
0
    {
3664
0
        if (nOpenFlags & GDAL_OF_INTERNAL)
3665
0
        {
3666
0
            CPLError(CE_Failure, CPLE_IllegalArg,
3667
0
                     "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3668
0
            return nullptr;
3669
0
        }
3670
3671
0
        auto poSharedDS =
3672
0
            GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
3673
0
        if (poSharedDS)
3674
0
        {
3675
0
            poSharedDS->Reference();
3676
0
            return poSharedDS;
3677
0
        }
3678
0
    }
3679
3680
0
    GDALDriverManager *poDM = GetGDALDriverManager();
3681
    // CPLLocaleC  oLocaleForcer;
3682
3683
0
    CPLErrorReset();
3684
0
    VSIErrorReset();
3685
0
    CPLAssert(nullptr != poDM);
3686
3687
    // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3688
    // shared dataset was asked before.
3689
0
    GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3690
0
                           const_cast<char **>(papszSiblingFiles));
3691
0
    oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3692
3693
0
    GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3694
0
    if (sAntiRecursion.nRecLevel == 100)
3695
0
    {
3696
0
        CPLError(CE_Failure, CPLE_AppDefined,
3697
0
                 "GDALOpen() called with too many recursion levels");
3698
0
        return nullptr;
3699
0
    }
3700
3701
0
    std::string osAllowedDrivers;
3702
0
    for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
3703
0
        osAllowedDrivers += pszDriverName;
3704
0
    auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
3705
0
        std::string(pszFilename), nOpenFlags, osAllowedDrivers);
3706
0
    if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))
3707
0
    {
3708
0
        CPLError(CE_Failure, CPLE_AppDefined,
3709
0
                 "GDALOpen() called on %s recursively", pszFilename);
3710
0
        return nullptr;
3711
0
    }
3712
3713
    // Remove leading @ if present.
3714
0
    char **papszOpenOptionsCleaned =
3715
0
        CSLDuplicate(const_cast<char **>(papszOpenOptions));
3716
0
    for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3717
0
         ++papszIter)
3718
0
    {
3719
0
        char *pszOption = *papszIter;
3720
0
        if (pszOption[0] == '@')
3721
0
            memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3722
0
    }
3723
3724
0
    oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3725
0
    oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
3726
3727
0
#ifdef OGRAPISPY_ENABLED
3728
0
    const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3729
0
    const int iSnapshot =
3730
0
        (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
3731
0
            ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
3732
0
            : INT_MIN;
3733
0
#endif
3734
3735
0
    const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
3736
0
    GDALDriver *poMissingPluginDriver = nullptr;
3737
0
    std::vector<GDALDriver *> apoSecondPassDrivers;
3738
3739
    // Lookup of matching driver for dataset can involve up to 2 passes:
3740
    // - in the first pass, all drivers that are compabile of the request mode
3741
    //   (raster/vector/etc.) are probed using their Identify() method if it
3742
    //   exists. If the Identify() method returns FALSE, the driver is skipped.
3743
    //   If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
3744
    //   driver is a deferred-loading plugin, it is added to the
3745
    //   apoSecondPassDrivers list for potential later probing, and execution
3746
    //   continues to the next driver in the list.
3747
    //   Otherwise if Identify() returns non-FALSE, the Open() method is used.
3748
    //   If Open() returns a non-NULL dataset, the loop stops and it is
3749
    //   returned. Otherwise looping over remaining drivers continues.
3750
    // - the second pass is optional, only if at least one driver was added
3751
    //   into apoSecondPassDrivers during the first pass. It is similar
3752
    //   to the first pass except it runs only on apoSecondPassDrivers drivers.
3753
    //   And the Open() method of such drivers is used, causing them to be
3754
    //   loaded for real.
3755
0
    int iPass = 1;
3756
0
retry:
3757
0
    for (int iDriver = 0;
3758
0
         iDriver < (iPass == 1 ? nDriverCount
3759
0
                               : static_cast<int>(apoSecondPassDrivers.size()));
3760
0
         ++iDriver)
3761
0
    {
3762
0
        GDALDriver *poDriver =
3763
0
            iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
3764
0
                       : apoSecondPassDrivers[iDriver];
3765
0
        if (papszAllowedDrivers != nullptr &&
3766
0
            CSLFindString(papszAllowedDrivers,
3767
0
                          GDALGetDriverShortName(poDriver)) == -1)
3768
0
        {
3769
0
            continue;
3770
0
        }
3771
3772
0
        if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
3773
0
            continue;
3774
3775
0
        if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
3776
0
            (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3777
0
            poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
3778
0
            continue;
3779
0
        if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3780
0
            (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3781
0
            poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
3782
0
            continue;
3783
0
        if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3784
0
            (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3785
0
            poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
3786
0
            continue;
3787
3788
        // Remove general OVERVIEW_LEVEL open options from list before passing
3789
        // it to the driver, if it isn't a driver specific option already.
3790
0
        char **papszTmpOpenOptions = nullptr;
3791
0
        char **papszTmpOpenOptionsToValidate = nullptr;
3792
0
        char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3793
0
        if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3794
0
                nullptr &&
3795
0
            !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3796
0
        {
3797
0
            papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3798
0
            papszTmpOpenOptions =
3799
0
                CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3800
0
            oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3801
3802
0
            papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3803
0
            papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
3804
0
                                                     "OVERVIEW_LEVEL", nullptr);
3805
0
            papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3806
0
        }
3807
3808
0
        const int nIdentifyRes =
3809
0
            poDriver->pfnIdentifyEx
3810
0
                ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
3811
0
            : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
3812
0
                                    : GDAL_IDENTIFY_UNKNOWN;
3813
0
        if (nIdentifyRes == FALSE)
3814
0
        {
3815
0
            CSLDestroy(papszTmpOpenOptions);
3816
0
            CSLDestroy(papszTmpOpenOptionsToValidate);
3817
0
            oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3818
0
            continue;
3819
0
        }
3820
0
        else if (iPass == 1 && nIdentifyRes < 0 &&
3821
0
                 poDriver->pfnOpen == nullptr &&
3822
0
                 poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
3823
0
        {
3824
            // Not loaded plugin
3825
0
            apoSecondPassDrivers.push_back(poDriver);
3826
0
            CSLDestroy(papszTmpOpenOptions);
3827
0
            CSLDestroy(papszTmpOpenOptionsToValidate);
3828
0
            oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3829
0
            continue;
3830
0
        }
3831
3832
0
        const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
3833
0
        if (bIdentifyRes)
3834
0
        {
3835
0
            GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3836
0
        }
3837
3838
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3839
0
        const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3840
0
        CPLErrorReset();
3841
0
#endif
3842
3843
0
        sAntiRecursion.nRecLevel++;
3844
0
        sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3845
3846
0
        GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
3847
3848
0
        sAntiRecursion.nRecLevel--;
3849
0
        sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3850
3851
0
        if (poDriver->pfnOpen != nullptr)
3852
0
        {
3853
            // If we couldn't determine for sure with Identify() (it returned
3854
            // -1), but Open() managed to open the file, post validate options.
3855
0
            if (poDS != nullptr &&
3856
0
                (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
3857
0
                !bIdentifyRes)
3858
0
            {
3859
0
                GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3860
0
            }
3861
0
        }
3862
0
        else if (poDriver->pfnOpenWithDriverArg != nullptr)
3863
0
        {
3864
            // do nothing
3865
0
        }
3866
0
        else if (bIdentifyRes &&
3867
0
                 poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
3868
0
        {
3869
0
            if (!poMissingPluginDriver)
3870
0
            {
3871
0
                poMissingPluginDriver = poDriver;
3872
0
            }
3873
0
        }
3874
0
        else
3875
0
        {
3876
            // should not happen given the GDAL_DCAP_OPEN check
3877
0
            CSLDestroy(papszTmpOpenOptions);
3878
0
            CSLDestroy(papszTmpOpenOptionsToValidate);
3879
0
            oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3880
0
            continue;
3881
0
        }
3882
3883
0
        CSLDestroy(papszTmpOpenOptions);
3884
0
        CSLDestroy(papszTmpOpenOptionsToValidate);
3885
0
        oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3886
3887
0
        if (poDS != nullptr)
3888
0
        {
3889
0
            if (poDS->papszOpenOptions == nullptr)
3890
0
            {
3891
0
                poDS->papszOpenOptions = papszOpenOptionsCleaned;
3892
0
                papszOpenOptionsCleaned = nullptr;
3893
0
            }
3894
3895
            // Deal with generic OVERVIEW_LEVEL open option, unless it is
3896
            // driver specific.
3897
0
            if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
3898
0
                    nullptr &&
3899
0
                !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3900
0
            {
3901
0
                CPLString osVal(
3902
0
                    CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
3903
0
                const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
3904
0
                const bool bThisLevelOnly =
3905
0
                    nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
3906
0
                GDALDataset *poOvrDS =
3907
0
                    GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
3908
0
                if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
3909
0
                {
3910
0
                    if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3911
0
                    {
3912
0
                        CPLError(
3913
0
                            CE_Warning, CPLE_NotSupported,
3914
0
                            "A dataset opened by GDALOpenShared should have "
3915
0
                            "the same filename (%s) "
3916
0
                            "and description (%s)",
3917
0
                            pszFilename, poDS->GetDescription());
3918
0
                    }
3919
0
                    else
3920
0
                    {
3921
0
                        CSLDestroy(poDS->papszOpenOptions);
3922
0
                        poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3923
0
                        poDS->papszOpenOptions = CSLSetNameValue(
3924
0
                            poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
3925
0
                    }
3926
0
                }
3927
0
                poDS->ReleaseRef();
3928
0
                poDS = poOvrDS;
3929
0
                if (poDS == nullptr)
3930
0
                {
3931
0
                    if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
3932
0
                    {
3933
0
                        CPLError(CE_Failure, CPLE_OpenFailed,
3934
0
                                 "Cannot open overview level %d of %s",
3935
0
                                 nOvrLevel, pszFilename);
3936
0
                    }
3937
0
                }
3938
0
                else
3939
0
                {
3940
                    // For thread-safe opening, currently poDS is what will be
3941
                    // the "master" dataset owned by the thread-safe dataset
3942
                    // returned to the user, hence we do not register it as a
3943
                    // visible one in the open dataset list, or mark it as shared.
3944
0
                    if (!(nOpenFlags & GDAL_OF_INTERNAL) &&
3945
0
                        !(nOpenFlags & GDAL_OF_THREAD_SAFE))
3946
0
                    {
3947
0
                        poDS->AddToDatasetOpenList();
3948
0
                    }
3949
0
                    if (nOpenFlags & GDAL_OF_SHARED)
3950
0
                    {
3951
0
                        CSLDestroy(poDS->papszOpenOptions);
3952
0
                        poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3953
0
                        poDS->nOpenFlags = nOpenFlags;
3954
0
                        if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
3955
0
                            poDS->MarkAsShared();
3956
0
                    }
3957
0
                }
3958
0
            }
3959
0
            else if (nOpenFlags & GDAL_OF_SHARED)
3960
0
            {
3961
0
                if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3962
0
                {
3963
0
                    CPLError(CE_Warning, CPLE_NotSupported,
3964
0
                             "A dataset opened by GDALOpenShared should have "
3965
0
                             "the same filename (%s) "
3966
0
                             "and description (%s)",
3967
0
                             pszFilename, poDS->GetDescription());
3968
0
                }
3969
0
                else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
3970
0
                {
3971
                    // For thread-safe opening, currently poDS is what will be
3972
                    // the "master" dataset owned by the thread-safe dataset
3973
                    // returned to the user, hence we do not or mark it as shared.
3974
0
                    poDS->MarkAsShared();
3975
0
                }
3976
0
            }
3977
3978
0
            VSIErrorReset();
3979
3980
0
            CSLDestroy(papszOpenOptionsCleaned);
3981
3982
0
#ifdef OGRAPISPY_ENABLED
3983
0
            if (iSnapshot != INT_MIN)
3984
0
            {
3985
0
                GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
3986
0
                OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3987
0
                poDS = GDALDataset::FromHandle(hDS);
3988
0
            }
3989
0
#endif
3990
3991
0
            if (poDS)
3992
0
            {
3993
0
                poDS->m_bCanBeReopened = true;
3994
3995
0
                if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3996
0
                {
3997
0
                    poDS =
3998
0
                        GDALGetThreadSafeDataset(
3999
0
                            std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)
4000
0
                            .release();
4001
0
                    if (poDS)
4002
0
                    {
4003
0
                        poDS->m_bCanBeReopened = true;
4004
0
                        poDS->poDriver = poDriver;
4005
0
                        poDS->nOpenFlags = nOpenFlags;
4006
0
                        if (!(nOpenFlags & GDAL_OF_INTERNAL))
4007
0
                            poDS->AddToDatasetOpenList();
4008
0
                        if (nOpenFlags & GDAL_OF_SHARED)
4009
0
                            poDS->MarkAsShared();
4010
0
                    }
4011
0
                }
4012
0
            }
4013
4014
0
            return poDS;
4015
0
        }
4016
4017
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4018
0
        if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
4019
0
        {
4020
            // In case the file descriptor was "consumed" by a driver
4021
            // that ultimately failed, re-open it for next drivers.
4022
0
            oOpenInfo.fpL = VSIFOpenL(
4023
0
                pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
4024
0
        }
4025
#else
4026
        if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
4027
        {
4028
            CSLDestroy(papszOpenOptionsCleaned);
4029
4030
#ifdef OGRAPISPY_ENABLED
4031
            if (iSnapshot != INT_MIN)
4032
            {
4033
                GDALDatasetH hDS = nullptr;
4034
                OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4035
            }
4036
#endif
4037
            return nullptr;
4038
        }
4039
#endif
4040
0
    }
4041
4042
    // cppcheck-suppress knownConditionTrueFalse
4043
0
    if (iPass == 1 && !apoSecondPassDrivers.empty())
4044
0
    {
4045
0
        CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
4046
0
        iPass = 2;
4047
0
        goto retry;
4048
0
    }
4049
4050
0
    CSLDestroy(papszOpenOptionsCleaned);
4051
4052
0
#ifdef OGRAPISPY_ENABLED
4053
0
    if (iSnapshot != INT_MIN)
4054
0
    {
4055
0
        GDALDatasetH hDS = nullptr;
4056
0
        OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4057
0
    }
4058
0
#endif
4059
4060
0
    if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4061
0
    {
4062
0
        if (nDriverCount == 0)
4063
0
        {
4064
0
            CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
4065
0
        }
4066
0
        else if (poMissingPluginDriver)
4067
0
        {
4068
0
            std::string osMsg("`");
4069
0
            osMsg += pszFilename;
4070
0
            osMsg += "' not recognized as being in a supported file format. "
4071
0
                     "It could have been recognized by driver ";
4072
0
            osMsg += poMissingPluginDriver->GetDescription();
4073
0
            osMsg += ", but plugin ";
4074
0
            osMsg +=
4075
0
                GDALGetMessageAboutMissingPluginDriver(poMissingPluginDriver);
4076
4077
0
            CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
4078
0
        }
4079
        // Check to see if there was a filesystem error, and report it if so.
4080
        // If not, return a more generic error.
4081
0
        else if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
4082
0
        {
4083
0
            if (oOpenInfo.bStatOK)
4084
0
            {
4085
0
                CPLError(CE_Failure, CPLE_OpenFailed,
4086
0
                         "`%s' not recognized as being in a supported file "
4087
0
                         "format.",
4088
0
                         pszFilename);
4089
0
            }
4090
0
            else
4091
0
            {
4092
                // If Stat failed and no VSI error was set, assume it is because
4093
                // the file did not exist on the filesystem.
4094
0
                CPLError(CE_Failure, CPLE_OpenFailed,
4095
0
                         "`%s' does not exist in the file system, "
4096
0
                         "and is not recognized as a supported dataset name.",
4097
0
                         pszFilename);
4098
0
            }
4099
0
        }
4100
0
    }
4101
4102
0
    return nullptr;
4103
0
}
4104
4105
/************************************************************************/
4106
/*                           GDALOpenShared()                           */
4107
/************************************************************************/
4108
4109
/**
4110
 * \brief Open a raster file as a GDALDataset.
4111
 *
4112
 * This function works the same as GDALOpen(), but allows the sharing of
4113
 * GDALDataset handles for a dataset with other callers to GDALOpenShared().
4114
 *
4115
 * In particular, GDALOpenShared() will first consult its list of currently
4116
 * open and shared GDALDataset's, and if the GetDescription() name for one
4117
 * exactly matches the pszFilename passed to GDALOpenShared() it will be
4118
 * referenced and returned.
4119
 *
4120
 * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
4121
 * pszFilename from two different threads, a different GDALDataset object will
4122
 * be returned as it is not safe to use the same dataset from different threads,
4123
 * unless the user does explicitly use mutexes in its code.
4124
 *
4125
 * For drivers supporting the VSI virtual file API, it is possible to open a
4126
 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
4127
 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
4128
 * server (see VSIInstallCurlFileHandler())
4129
 *
4130
 * \sa GDALOpen()
4131
 * \sa GDALOpenEx()
4132
 *
4133
 * @param pszFilename the name of the file to access.  In the case of
4134
 * exotic drivers this may not refer to a physical file, but instead contain
4135
 * information for the driver on how to access a dataset.  It should be in
4136
 * UTF-8 encoding.
4137
 *
4138
 * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
4139
 * drivers support only read only access.
4140
 *
4141
 * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
4142
 * this handle can be cast to a GDALDataset *.
4143
 */
4144
4145
GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4146
                                        GDALAccess eAccess)
4147
0
{
4148
0
    VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4149
0
    return GDALOpenEx(pszFilename,
4150
0
                      GDAL_OF_RASTER |
4151
0
                          (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4152
0
                          GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4153
0
                      nullptr, nullptr, nullptr);
4154
0
}
4155
4156
/************************************************************************/
4157
/*                             GDALClose()                              */
4158
/************************************************************************/
4159
4160
/**
4161
 * \brief Close GDAL dataset.
4162
 *
4163
 * For non-shared datasets (opened with GDALOpen()) the dataset is closed
4164
 * using the C++ "delete" operator, recovering all dataset related resources.
4165
 * For shared datasets (opened with GDALOpenShared()) the dataset is
4166
 * dereferenced, and closed only if the referenced count has dropped below 1.
4167
 *
4168
 * @param hDS The dataset to close.  May be cast from a "GDALDataset *".
4169
 * @return CE_None in case of success (return value since GDAL 3.7). On a
4170
 * shared dataset whose reference count is not dropped below 1, CE_None will
4171
 * be returned.
4172
 */
4173
4174
CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4175
4176
0
{
4177
0
    if (!hDS)
4178
0
        return CE_None;
4179
4180
0
#ifdef OGRAPISPY_ENABLED
4181
0
    if (bOGRAPISpyEnabled)
4182
0
        OGRAPISpyPreClose(hDS);
4183
0
#endif
4184
4185
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4186
4187
0
    if (poDS->GetShared())
4188
0
    {
4189
        /* --------------------------------------------------------------------
4190
         */
4191
        /*      If this file is in the shared dataset list then dereference */
4192
        /*      it, and only delete/remote it if the reference count has */
4193
        /*      dropped to zero. */
4194
        /* --------------------------------------------------------------------
4195
         */
4196
0
        if (poDS->Dereference() > 0)
4197
0
            return CE_None;
4198
4199
0
        CPLErr eErr = poDS->Close();
4200
0
        delete poDS;
4201
4202
0
#ifdef OGRAPISPY_ENABLED
4203
0
        if (bOGRAPISpyEnabled)
4204
0
            OGRAPISpyPostClose();
4205
0
#endif
4206
4207
0
        return eErr;
4208
0
    }
4209
4210
    /* -------------------------------------------------------------------- */
4211
    /*      This is not shared dataset, so directly delete it.              */
4212
    /* -------------------------------------------------------------------- */
4213
0
    CPLErr eErr = poDS->Close();
4214
0
    delete poDS;
4215
4216
0
#ifdef OGRAPISPY_ENABLED
4217
0
    if (bOGRAPISpyEnabled)
4218
0
        OGRAPISpyPostClose();
4219
0
#endif
4220
0
    return eErr;
4221
0
}
4222
4223
/************************************************************************/
4224
/*                        GDALDumpOpenDataset()                         */
4225
/************************************************************************/
4226
4227
static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
4228
0
{
4229
0
    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
4230
0
    FILE *fp = static_cast<FILE *>(user_data);
4231
0
    GDALDataset *poDS = psStruct->poDS;
4232
4233
0
    const char *pszDriverName = poDS->GetDriver() == nullptr
4234
0
                                    ? "DriverIsNULL"
4235
0
                                    : poDS->GetDriver()->GetDescription();
4236
4237
0
    poDS->Reference();
4238
0
    CPL_IGNORE_RET_VAL(
4239
0
        VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4240
0
                   poDS->GetShared() ? 'S' : 'N', pszDriverName,
4241
0
                   static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
4242
0
                   poDS->GetRasterYSize(), poDS->GetRasterCount(),
4243
0
                   poDS->GetDescription()));
4244
4245
0
    return TRUE;
4246
0
}
4247
4248
static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
4249
0
{
4250
4251
    // Don't list shared datasets. They have already been listed by
4252
    // GDALDumpOpenSharedDatasetsForeach.
4253
0
    if (poDS->GetShared())
4254
0
        return TRUE;
4255
4256
0
    const char *pszDriverName = poDS->GetDriver() == nullptr
4257
0
                                    ? "DriverIsNULL"
4258
0
                                    : poDS->GetDriver()->GetDescription();
4259
4260
0
    poDS->Reference();
4261
0
    CPL_IGNORE_RET_VAL(
4262
0
        VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4263
0
                   poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
4264
0
                   poDS->GetRasterXSize(), poDS->GetRasterYSize(),
4265
0
                   poDS->GetRasterCount(), poDS->GetDescription()));
4266
4267
0
    return TRUE;
4268
0
}
4269
4270
/**
4271
 * \brief List open datasets.
4272
 *
4273
 * Dumps a list of all open datasets (shared or not) to the indicated
4274
 * text file (may be stdout or stderr).   This function is primarily intended
4275
 * to assist in debugging "dataset leaks" and reference counting issues.
4276
 * The information reported includes the dataset name, referenced count,
4277
 * shared status, driver name, size, and band count.
4278
 */
4279
4280
int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
4281
4282
0
{
4283
0
    VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
4284
4285
0
    CPLMutexHolderD(&hDLMutex);
4286
4287
0
    if (poAllDatasetMap == nullptr)
4288
0
        return 0;
4289
4290
0
    CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
4291
4292
0
    for (const auto &oIter : *poAllDatasetMap)
4293
0
    {
4294
0
        GDALDumpOpenDatasetsForeach(oIter.first, fp);
4295
0
    }
4296
4297
0
    if (phSharedDatasetSet != nullptr)
4298
0
    {
4299
0
        CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
4300
0
                          fp);
4301
0
    }
4302
0
    return static_cast<int>(poAllDatasetMap->size());
4303
0
}
4304
4305
/************************************************************************/
4306
/*                        BeginAsyncReader()                            */
4307
/************************************************************************/
4308
4309
/**
4310
 * \brief Sets up an asynchronous data request
4311
 *
4312
 * This method establish an asynchronous raster read request for the
4313
 * indicated window on the dataset into the indicated buffer.  The parameters
4314
 * for windowing, buffer size, buffer type and buffer organization are similar
4315
 * to those for GDALDataset::RasterIO(); however, this call only launches
4316
 * the request and filling the buffer is accomplished via calls to
4317
 * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4318
 *
4319
 * Once all processing for the created session is complete, or if no further
4320
 * refinement of the request is required, the GDALAsyncReader object should
4321
 * be destroyed with the GDALDataset::EndAsyncReader() method.
4322
 *
4323
 * Note that the data buffer (pData) will potentially continue to be
4324
 * updated as long as the session lives, but it is not deallocated when
4325
 * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
4326
 * should be deallocated by the application at that point.
4327
 *
4328
 * Additional information on asynchronous IO in GDAL may be found at:
4329
 *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4330
 *
4331
 * This method is the same as the C GDALBeginAsyncReader() function.
4332
 *
4333
 * @param nXOff The pixel offset to the top left corner of the region
4334
 * of the band to be accessed.  This would be zero to start from the left side.
4335
 *
4336
 * @param nYOff The line offset to the top left corner of the region
4337
 * of the band to be accessed.  This would be zero to start from the top.
4338
 *
4339
 * @param nXSize The width of the region of the band to be accessed in pixels.
4340
 *
4341
 * @param nYSize The height of the region of the band to be accessed in lines.
4342
 *
4343
 * @param pBuf The buffer into which the data should be read. This buffer must
4344
 * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4345
 * It is organized in left to right,top to bottom pixel order.  Spacing is
4346
 * controlled by the nPixelSpace, and nLineSpace parameters.
4347
 *
4348
 * @param nBufXSize the width of the buffer image into which the desired region
4349
 * is to be read, or from which it is to be written.
4350
 *
4351
 * @param nBufYSize the height of the buffer image into which the desired
4352
 * region is to be read, or from which it is to be written.
4353
 *
4354
 * @param eBufType the type of the pixel values in the pData data buffer.  The
4355
 * pixel values will automatically be translated to/from the GDALRasterBand
4356
 * data type as needed.
4357
 *
4358
 * @param nBandCount the number of bands being read or written.
4359
 *
4360
 * @param panBandMap the list of nBandCount band numbers being read/written.
4361
 * Note band numbers are 1 based.   This may be NULL to select the first
4362
 * nBandCount bands.
4363
 *
4364
 * @param nPixelSpace The byte offset from the start of one pixel value in
4365
 * pData to the start of the next pixel value within a scanline.  If defaulted
4366
 * (0) the size of the datatype eBufType is used.
4367
 *
4368
 * @param nLineSpace The byte offset from the start of one scanline in
4369
 * pData to the start of the next.  If defaulted the size of the datatype
4370
 * eBufType * nBufXSize is used.
4371
 *
4372
 * @param nBandSpace the byte offset from the start of one bands data to the
4373
 * start of the next.  If defaulted (zero) the value will be
4374
 * nLineSpace * nBufYSize implying band sequential organization
4375
 * of the data buffer.
4376
 *
4377
 * @param papszOptions Driver specific control options in a string list or NULL.
4378
 * Consult driver documentation for options supported.
4379
 *
4380
 * @return The GDALAsyncReader object representing the request.
4381
 */
4382
4383
GDALAsyncReader *GDALDataset::BeginAsyncReader(
4384
    int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
4385
    int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
4386
    int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
4387
0
{
4388
    // See gdaldefaultasync.cpp
4389
4390
0
    return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
4391
0
                                     nBufXSize, nBufYSize, eBufType, nBandCount,
4392
0
                                     panBandMap, nPixelSpace, nLineSpace,
4393
0
                                     nBandSpace, papszOptions);
4394
0
}
4395
4396
/************************************************************************/
4397
/*                        GDALBeginAsyncReader()                      */
4398
/************************************************************************/
4399
4400
/**
4401
 * \brief Sets up an asynchronous data request
4402
 *
4403
 * This method establish an asynchronous raster read request for the
4404
 * indicated window on the dataset into the indicated buffer.  The parameters
4405
 * for windowing, buffer size, buffer type and buffer organization are similar
4406
 * to those for GDALDataset::RasterIO(); however, this call only launches
4407
 * the request and filling the buffer is accomplished via calls to
4408
 * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4409
 *
4410
 * Once all processing for the created session is complete, or if no further
4411
 * refinement of the request is required, the GDALAsyncReader object should
4412
 * be destroyed with the GDALDataset::EndAsyncReader() method.
4413
 *
4414
 * Note that the data buffer (pData) will potentially continue to be
4415
 * updated as long as the session lives, but it is not deallocated when
4416
 * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
4417
 * should be deallocated by the application at that point.
4418
 *
4419
 * Additional information on asynchronous IO in GDAL may be found at:
4420
 *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4421
 *
4422
 * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
4423
 *
4424
 * @param hDS handle to the dataset object.
4425
 *
4426
 * @param nXOff The pixel offset to the top left corner of the region
4427
 * of the band to be accessed.  This would be zero to start from the left side.
4428
 *
4429
 * @param nYOff The line offset to the top left corner of the region
4430
 * of the band to be accessed.  This would be zero to start from the top.
4431
 *
4432
 * @param nXSize The width of the region of the band to be accessed in pixels.
4433
 *
4434
 * @param nYSize The height of the region of the band to be accessed in lines.
4435
 *
4436
 * @param pBuf The buffer into which the data should be read. This buffer must
4437
 * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4438
 * It is organized in left to right,top to bottom pixel order.  Spacing is
4439
 * controlled by the nPixelSpace, and nLineSpace parameters.
4440
 *
4441
 * @param nBufXSize the width of the buffer image into which the desired region
4442
 * is to be read, or from which it is to be written.
4443
 *
4444
 * @param nBufYSize the height of the buffer image into which the desired
4445
 * region is to be read, or from which it is to be written.
4446
 *
4447
 * @param eBufType the type of the pixel values in the pData data buffer.  The
4448
 * pixel values will automatically be translated to/from the GDALRasterBand
4449
 * data type as needed.
4450
 *
4451
 * @param nBandCount the number of bands being read or written.
4452
 *
4453
 * @param panBandMap the list of nBandCount band numbers being read/written.
4454
 * Note band numbers are 1 based.   This may be NULL to select the first
4455
 * nBandCount bands.
4456
 *
4457
 * @param nPixelSpace The byte offset from the start of one pixel value in
4458
 * pData to the start of the next pixel value within a scanline.  If defaulted
4459
 * (0) the size of the datatype eBufType is used.
4460
 *
4461
 * @param nLineSpace The byte offset from the start of one scanline in
4462
 * pData to the start of the next.  If defaulted the size of the datatype
4463
 * eBufType * nBufXSize is used.
4464
 *
4465
 * @param nBandSpace the byte offset from the start of one bands data to the
4466
 * start of the next.  If defaulted (zero) the value will be
4467
 * nLineSpace * nBufYSize implying band sequential organization
4468
 * of the data buffer.
4469
 *
4470
 * @param papszOptions Driver specific control options in a string list or NULL.
4471
 * Consult driver documentation for options supported.
4472
 *
4473
 * @return handle representing the request.
4474
 */
4475
4476
GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
4477
    GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
4478
    int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
4479
    int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
4480
    CSLConstList papszOptions)
4481
4482
0
{
4483
0
    VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
4484
0
    return static_cast<GDALAsyncReaderH>(
4485
0
        GDALDataset::FromHandle(hDS)->BeginAsyncReader(
4486
0
            nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
4487
0
            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
4488
0
            const_cast<char **>(papszOptions)));
4489
0
}
4490
4491
/************************************************************************/
4492
/*                        EndAsyncReader()                            */
4493
/************************************************************************/
4494
4495
/**
4496
 * End asynchronous request.
4497
 *
4498
 * This method destroys an asynchronous io request and recovers all
4499
 * resources associated with it.
4500
 *
4501
 * This method is the same as the C function GDALEndAsyncReader().
4502
 *
4503
 * @param poARIO pointer to a GDALAsyncReader
4504
 */
4505
4506
void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
4507
0
{
4508
0
    delete poARIO;
4509
0
}
4510
4511
/************************************************************************/
4512
/*                        GDALEndAsyncReader()                        */
4513
/************************************************************************/
4514
4515
/**
4516
 * End asynchronous request.
4517
 *
4518
 * This method destroys an asynchronous io request and recovers all
4519
 * resources associated with it.
4520
 *
4521
 * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4522
 *
4523
 * @param hDS handle to the dataset object.
4524
 * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4525
 */
4526
4527
void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
4528
                                    GDALAsyncReaderH hAsyncReaderH)
4529
0
{
4530
0
    VALIDATE_POINTER0(hDS, "GDALDataset");
4531
0
    VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4532
0
    GDALDataset::FromHandle(hDS)->EndAsyncReader(
4533
0
        static_cast<GDALAsyncReader *>(hAsyncReaderH));
4534
0
}
4535
4536
/************************************************************************/
4537
/*                       CloseDependentDatasets()                       */
4538
/************************************************************************/
4539
4540
/**
4541
 * Drop references to any other datasets referenced by this dataset.
4542
 *
4543
 * This method should release any reference to other datasets (e.g. a VRT
4544
 * dataset to its sources), but not close the current dataset itself.
4545
 *
4546
 * If at least, one reference to a dependent dataset has been dropped,
4547
 * this method should return TRUE. Otherwise it *should* return FALSE.
4548
 * (Failure to return the proper value might result in infinite loop)
4549
 *
4550
 * This method can be called several times on a given dataset. After
4551
 * the first time, it should not do anything and return FALSE.
4552
 *
4553
 * The driver implementation may choose to destroy its raster bands,
4554
 * so be careful not to call any method on the raster bands afterwards.
4555
 *
4556
 * Basically the only safe action you can do after calling
4557
 * CloseDependentDatasets() is to call the destructor.
4558
 *
4559
 * Note: the only legitimate caller of CloseDependentDatasets() is
4560
 * GDALDriverManager::~GDALDriverManager()
4561
 *
4562
 * @return TRUE if at least one reference to another dataset has been dropped.
4563
 */
4564
int GDALDataset::CloseDependentDatasets()
4565
0
{
4566
0
    return oOvManager.CloseDependentDatasets();
4567
0
}
4568
4569
/************************************************************************/
4570
/*                            ReportError()                             */
4571
/************************************************************************/
4572
4573
#ifndef DOXYGEN_XML
4574
/**
4575
 * \brief Emits an error related to a dataset.
4576
 *
4577
 * This function is a wrapper for regular CPLError(). The only difference
4578
 * with CPLError() is that it prepends the error message with the dataset
4579
 * name.
4580
 *
4581
 * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4582
 * @param err_no the error number (CPLE_*) from cpl_error.h.
4583
 * @param fmt a printf() style format string.  Any additional arguments
4584
 * will be treated as arguments to fill in this format in a manner
4585
 * similar to printf().
4586
 *
4587
 * @since GDAL 1.9.0
4588
 */
4589
4590
void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4591
                              const char *fmt, ...) const
4592
0
{
4593
0
    va_list args;
4594
0
    va_start(args, fmt);
4595
0
    ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4596
0
    va_end(args);
4597
0
}
4598
4599
/**
4600
 * \brief Emits an error related to a dataset (static method)
4601
 *
4602
 * This function is a wrapper for regular CPLError(). The only difference
4603
 * with CPLError() is that it prepends the error message with the dataset
4604
 * name.
4605
 *
4606
 * @param pszDSName dataset name.
4607
 * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4608
 * @param err_no the error number (CPLE_*) from cpl_error.h.
4609
 * @param fmt a printf() style format string.  Any additional arguments
4610
 * will be treated as arguments to fill in this format in a manner
4611
 * similar to printf().
4612
 *
4613
 * @since GDAL 3.2.0
4614
 */
4615
4616
void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4617
                              CPLErrorNum err_no, const char *fmt, ...)
4618
0
{
4619
0
    va_list args;
4620
0
    va_start(args, fmt);
4621
0
    ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4622
0
    va_end(args);
4623
0
}
4624
4625
void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4626
                               CPLErrorNum err_no, const char *fmt,
4627
                               va_list args)
4628
0
{
4629
0
    pszDSName = CPLGetFilename(pszDSName);
4630
0
    if (pszDSName[0] != '\0')
4631
0
    {
4632
0
        CPLError(eErrClass, err_no, "%s",
4633
0
                 std::string(pszDSName)
4634
0
                     .append(": ")
4635
0
                     .append(CPLString().vPrintf(fmt, args))
4636
0
                     .c_str());
4637
0
    }
4638
0
    else
4639
0
    {
4640
0
        CPLErrorV(eErrClass, err_no, fmt, args);
4641
0
    }
4642
0
}
4643
#endif
4644
4645
/************************************************************************/
4646
/*                            GetMetadata()                             */
4647
/************************************************************************/
4648
char **GDALDataset::GetMetadata(const char *pszDomain)
4649
0
{
4650
#ifndef WITHOUT_DERIVED
4651
    if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4652
    {
4653
        oDerivedMetadataList.Clear();
4654
4655
        // First condition: at least one raster band.
4656
        if (GetRasterCount() > 0)
4657
        {
4658
            // Check if there is at least one complex band.
4659
            bool hasAComplexBand = false;
4660
4661
            for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4662
            {
4663
                if (GDALDataTypeIsComplex(
4664
                        GetRasterBand(rasterId)->GetRasterDataType()))
4665
                {
4666
                    hasAComplexBand = true;
4667
                    break;
4668
                }
4669
            }
4670
4671
            unsigned int nbSupportedDerivedDS = 0;
4672
            const DerivedDatasetDescription *poDDSDesc =
4673
                GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4674
4675
            int nNumDataset = 1;
4676
            for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4677
                 ++derivedId)
4678
            {
4679
                if (hasAComplexBand ||
4680
                    CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4681
                        "complex")
4682
                {
4683
                    oDerivedMetadataList.SetNameValue(
4684
                        CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4685
                        CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4686
                                   poDDSDesc[derivedId].pszDatasetName,
4687
                                   GetDescription()));
4688
4689
                    CPLString osDesc(
4690
                        CPLSPrintf("%s from %s",
4691
                                   poDDSDesc[derivedId].pszDatasetDescription,
4692
                                   GetDescription()));
4693
                    oDerivedMetadataList.SetNameValue(
4694
                        CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4695
                        osDesc.c_str());
4696
4697
                    nNumDataset++;
4698
                }
4699
            }
4700
        }
4701
        return oDerivedMetadataList.List();
4702
    }
4703
#endif
4704
4705
0
    return GDALMajorObject::GetMetadata(pszDomain);
4706
0
}
4707
4708
// clang-format off
4709
4710
/**
4711
 * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4712
 * \brief Set metadata.
4713
 *
4714
 * CAUTION: depending on the format, older values of the updated information
4715
 * might still be found in the file in a "ghost" state, even if no longer
4716
 * accessible through the GDAL API. This is for example the case of the GTiff
4717
 * format (this is not a exhaustive list)
4718
 *
4719
 * The C function GDALSetMetadata() does the same thing as this method.
4720
 *
4721
 * @param papszMetadata the metadata in name=value string list format to
4722
 * apply.
4723
 * @param pszDomain the domain of interest.  Use "" or NULL for the default
4724
 * domain.
4725
 * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4726
 * metadata has been accepted, but is likely not maintained persistently
4727
 * by the underlying object between sessions.
4728
 */
4729
4730
/**
4731
 * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
4732
 * \brief Set single metadata item.
4733
 *
4734
 * CAUTION: depending on the format, older values of the updated information
4735
 * might still be found in the file in a "ghost" state, even if no longer
4736
 * accessible through the GDAL API. This is for example the case of the GTiff
4737
 * format (this is not a exhaustive list)
4738
 *
4739
 * The C function GDALSetMetadataItem() does the same thing as this method.
4740
 *
4741
 * @param pszName the key for the metadata item to fetch.
4742
 * @param pszValue the value to assign to the key.
4743
 * @param pszDomain the domain to set within, use NULL for the default domain.
4744
 *
4745
 * @return CE_None on success, or an error code on failure.
4746
 */
4747
4748
// clang-format on
4749
4750
/************************************************************************/
4751
/*                            GetMetadataDomainList()                   */
4752
/************************************************************************/
4753
4754
char **GDALDataset::GetMetadataDomainList()
4755
0
{
4756
0
    char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4757
4758
    // Ensure that we do not duplicate DERIVED domain.
4759
0
    if (GetRasterCount() > 0 &&
4760
0
        CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4761
0
    {
4762
0
        currentDomainList =
4763
0
            CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4764
0
    }
4765
0
    return currentDomainList;
4766
0
}
4767
4768
/************************************************************************/
4769
/*                            GetDriverName()                           */
4770
/************************************************************************/
4771
4772
/** Return driver name.
4773
 * @return driver name.
4774
 */
4775
const char *GDALDataset::GetDriverName()
4776
0
{
4777
0
    if (poDriver)
4778
0
        return poDriver->GetDescription();
4779
0
    return "";
4780
0
}
4781
4782
/************************************************************************/
4783
/*                     GDALDatasetReleaseResultSet()                    */
4784
/************************************************************************/
4785
4786
/**
4787
 \brief Release results of ExecuteSQL().
4788
4789
 This function should only be used to deallocate OGRLayers resulting from
4790
 an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
4791
 results set before destroying the GDALDataset may cause errors.
4792
4793
 This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4794
4795
 @since GDAL 2.0
4796
4797
 @param hDS the dataset handle.
4798
 @param hLayer the result of a previous ExecuteSQL() call.
4799
4800
*/
4801
void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
4802
4803
0
{
4804
0
    VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4805
4806
0
#ifdef OGRAPISPY_ENABLED
4807
0
    if (bOGRAPISpyEnabled)
4808
0
        OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4809
0
#endif
4810
4811
0
    GDALDataset::FromHandle(hDS)->ReleaseResultSet(
4812
0
        OGRLayer::FromHandle(hLayer));
4813
0
}
4814
4815
/************************************************************************/
4816
/*                       GDALDatasetGetLayerCount()                     */
4817
/************************************************************************/
4818
4819
/**
4820
 \brief Get the number of layers in this dataset.
4821
4822
 This function is the same as the C++ method GDALDataset::GetLayerCount()
4823
4824
 @since GDAL 2.0
4825
4826
 @param hDS the dataset handle.
4827
 @return layer count.
4828
*/
4829
4830
int GDALDatasetGetLayerCount(GDALDatasetH hDS)
4831
4832
0
{
4833
0
    VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4834
4835
0
#ifdef OGRAPISPY_ENABLED
4836
0
    if (bOGRAPISpyEnabled)
4837
0
        OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4838
0
#endif
4839
4840
0
    return GDALDataset::FromHandle(hDS)->GetLayerCount();
4841
0
}
4842
4843
/************************************************************************/
4844
/*                        GDALDatasetGetLayer()                         */
4845
/************************************************************************/
4846
4847
/**
4848
 \brief Fetch a layer by index.
4849
4850
 The returned layer remains owned by the
4851
 GDALDataset and should not be deleted by the application.
4852
4853
 This function is the same as the C++ method GDALDataset::GetLayer()
4854
4855
 @since GDAL 2.0
4856
4857
 @param hDS the dataset handle.
4858
 @param iLayer a layer number between 0 and GetLayerCount()-1.
4859
4860
 @return the layer, or NULL if iLayer is out of range or an error occurs.
4861
*/
4862
4863
OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
4864
4865
0
{
4866
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
4867
4868
0
    OGRLayerH hLayer =
4869
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
4870
4871
0
#ifdef OGRAPISPY_ENABLED
4872
0
    if (bOGRAPISpyEnabled)
4873
0
        OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
4874
0
#endif
4875
4876
0
    return hLayer;
4877
0
}
4878
4879
/************************************************************************/
4880
/*                     GDALDatasetGetLayerByName()                      */
4881
/************************************************************************/
4882
4883
/**
4884
 \brief Fetch a layer by name.
4885
4886
 The returned layer remains owned by the
4887
 GDALDataset and should not be deleted by the application.
4888
4889
 This function is the same as the C++ method GDALDataset::GetLayerByName()
4890
4891
 @since GDAL 2.0
4892
4893
 @param hDS the dataset handle.
4894
 @param pszName the layer name of the layer to fetch.
4895
4896
 @return the layer, or NULL if Layer is not found or an error occurs.
4897
*/
4898
4899
OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
4900
4901
0
{
4902
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
4903
4904
0
    OGRLayerH hLayer = OGRLayer::ToHandle(
4905
0
        GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
4906
4907
0
#ifdef OGRAPISPY_ENABLED
4908
0
    if (bOGRAPISpyEnabled)
4909
0
        OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
4910
0
#endif
4911
4912
0
    return hLayer;
4913
0
}
4914
4915
/************************************************************************/
4916
/*                        GDALDatasetIsLayerPrivate()                   */
4917
/************************************************************************/
4918
4919
/**
4920
 \brief Returns true if the layer at the specified index is deemed a private or
4921
 system table, or an internal detail only.
4922
4923
 This function is the same as the C++ method GDALDataset::IsLayerPrivate()
4924
4925
 @since GDAL 3.4
4926
4927
 @param hDS the dataset handle.
4928
 @param iLayer a layer number between 0 and GetLayerCount()-1.
4929
4930
 @return true if the layer is a private or system table.
4931
*/
4932
4933
int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
4934
4935
0
{
4936
0
    VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
4937
4938
0
    const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
4939
4940
0
    return res ? 1 : 0;
4941
0
}
4942
4943
/************************************************************************/
4944
/*                            GetLayerIndex()                           */
4945
/************************************************************************/
4946
4947
/**
4948
 \brief Returns the index of the layer specified by name.
4949
4950
 @since GDAL 3.12
4951
4952
 @param pszName layer name (not NULL)
4953
4954
 @return an index >= 0, or -1 if not found.
4955
*/
4956
4957
int GDALDataset::GetLayerIndex(const char *pszName)
4958
0
{
4959
0
    const int nLayerCount = GetLayerCount();
4960
0
    int iMatch = -1;
4961
0
    for (int i = 0; i < nLayerCount; ++i)
4962
0
    {
4963
0
        if (const auto poLayer = GetLayer(i))
4964
0
        {
4965
0
            const char *pszLayerName = poLayer->GetDescription();
4966
0
            if (strcmp(pszName, pszLayerName) == 0)
4967
0
            {
4968
0
                iMatch = i;
4969
0
                break;
4970
0
            }
4971
0
            else if (EQUAL(pszName, pszLayerName))
4972
0
            {
4973
0
                iMatch = i;
4974
0
            }
4975
0
        }
4976
0
    }
4977
0
    return iMatch;
4978
0
}
4979
4980
/************************************************************************/
4981
/*                        GDALDatasetDeleteLayer()                      */
4982
/************************************************************************/
4983
4984
/**
4985
 \brief Delete the indicated layer from the datasource.
4986
4987
 If this function is supported
4988
 the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
4989
4990
 This method is the same as the C++ method GDALDataset::DeleteLayer().
4991
4992
 @since GDAL 2.0
4993
4994
 @param hDS the dataset handle.
4995
 @param iLayer the index of the layer to delete.
4996
4997
 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
4998
 layers is not supported for this datasource.
4999
5000
*/
5001
OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
5002
5003
0
{
5004
0
    VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
5005
5006
0
#ifdef OGRAPISPY_ENABLED
5007
0
    if (bOGRAPISpyEnabled)
5008
0
        OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
5009
0
#endif
5010
5011
0
    return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
5012
0
}
5013
5014
/************************************************************************/
5015
/*                            CreateLayer()                             */
5016
/************************************************************************/
5017
5018
/**
5019
\brief This method attempts to create a new layer on the dataset with the
5020
indicated name, coordinate system, geometry type.
5021
5022
The papszOptions argument
5023
can be used to control driver specific creation options.  These options are
5024
normally documented in the format specific documentation.
5025
That function will try to validate the creation option list passed to the
5026
driver with the GDALValidateCreationOptions() method. This check can be
5027
disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5028
to NO.
5029
5030
Drivers should extend the ICreateLayer() method and not
5031
CreateLayer(). CreateLayer() adds validation of layer creation options, before
5032
delegating the actual work to ICreateLayer().
5033
5034
This method is the same as the C function GDALDatasetCreateLayer() and the
5035
deprecated OGR_DS_CreateLayer().
5036
5037
Example:
5038
5039
\code{.cpp}
5040
#include "gdal.h"
5041
#include "cpl_string.h"
5042
5043
...
5044
5045
        OGRLayer *poLayer;
5046
        char     **papszOptions;
5047
5048
        if( !poDS->TestCapability( ODsCCreateLayer ) )
5049
        {
5050
        ...
5051
        }
5052
5053
        papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5054
        poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
5055
                                     papszOptions );
5056
        CSLDestroy( papszOptions );
5057
5058
        if( poLayer == NULL )
5059
        {
5060
            ...
5061
        }
5062
\endcode
5063
5064
@param pszName the name for the new layer.  This should ideally not
5065
match any existing layer on the datasource.
5066
@param poSpatialRef the coordinate system to use for the new layer, or NULL if
5067
no coordinate system is available.
5068
@param eGType the geometry type for the layer.  Use wkbUnknown if there
5069
are no constraints on the types geometry to be written.
5070
@param papszOptions a StringList of name=value options.  Options are driver
5071
specific.
5072
5073
@return NULL is returned on failure, or a new OGRLayer handle on success.
5074
5075
*/
5076
5077
OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5078
                                   const OGRSpatialReference *poSpatialRef,
5079
                                   OGRwkbGeometryType eGType,
5080
                                   CSLConstList papszOptions)
5081
5082
0
{
5083
0
    if (eGType == wkbNone)
5084
0
    {
5085
0
        return CreateLayer(pszName, nullptr, papszOptions);
5086
0
    }
5087
0
    else
5088
0
    {
5089
0
        OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5090
0
        oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5091
0
        return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5092
0
    }
5093
0
}
5094
5095
/**
5096
\brief This method attempts to create a new layer on the dataset with the
5097
indicated name and geometry field definition.
5098
5099
When poGeomFieldDefn is not null, most drivers should honor
5100
poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5101
Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5102
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5103
poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5104
very few currently.
5105
5106
Note that even if a geometry coordinate precision is set and a driver honors the
5107
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5108
OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5109
with the coordinate precision. That is they are assumed to be valid once their
5110
coordinates are rounded to it. If it might not be the case, the user may set
5111
the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5112
or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5113
the passed geometries.
5114
5115
The papszOptions argument
5116
can be used to control driver specific creation options. These options are
5117
normally documented in the format specific documentation.
5118
This function will try to validate the creation option list passed to the
5119
driver with the GDALValidateCreationOptions() method. This check can be
5120
disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5121
to NO.
5122
5123
Drivers should extend the ICreateLayer() method and not
5124
CreateLayer(). CreateLayer() adds validation of layer creation options, before
5125
delegating the actual work to ICreateLayer().
5126
5127
This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5128
5129
@param pszName the name for the new layer.  This should ideally not
5130
match any existing layer on the datasource.
5131
@param poGeomFieldDefn the geometry field definition to use for the new layer,
5132
or NULL if there is no geometry field.
5133
@param papszOptions a StringList of name=value options.  Options are driver
5134
specific.
5135
5136
@return NULL is returned on failure, or a new OGRLayer handle on success.
5137
@since 3.9
5138
5139
*/
5140
5141
OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5142
                                   const OGRGeomFieldDefn *poGeomFieldDefn,
5143
                                   CSLConstList papszOptions)
5144
5145
0
{
5146
0
    if (CPLTestBool(
5147
0
            CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5148
0
    {
5149
0
        ValidateLayerCreationOptions(papszOptions);
5150
0
    }
5151
5152
0
    OGRLayer *poLayer;
5153
0
    if (poGeomFieldDefn)
5154
0
    {
5155
0
        OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5156
0
        if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5157
0
            !TestCapability(ODsCCurveGeometries))
5158
0
        {
5159
0
            oGeomFieldDefn.SetType(
5160
0
                OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5161
0
        }
5162
5163
0
        poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5164
0
    }
5165
0
    else
5166
0
    {
5167
0
        poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5168
0
    }
5169
0
#ifdef DEBUG
5170
0
    if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5171
0
        !poLayer->TestCapability(OLCCurveGeometries))
5172
0
    {
5173
0
        CPLError(CE_Warning, CPLE_AppDefined,
5174
0
                 "Inconsistent driver: Layer geometry type is non-linear, but "
5175
0
                 "TestCapability(OLCCurveGeometries) returns FALSE.");
5176
0
    }
5177
0
#endif
5178
5179
0
    return poLayer;
5180
0
}
5181
5182
//! @cond Doxygen_Suppress
5183
5184
// Technical override to avoid ambiguous choice between the old and new
5185
// new CreateLayer() signatures.
5186
OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5187
0
{
5188
0
    OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5189
0
    return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5190
0
}
5191
5192
// Technical override to avoid ambiguous choice between the old and new
5193
// new CreateLayer() signatures.
5194
OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5195
0
{
5196
0
    OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5197
0
    return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5198
0
}
5199
5200
//!@endcond
5201
5202
/************************************************************************/
5203
/*                         GDALDatasetCreateLayer()                     */
5204
/************************************************************************/
5205
5206
/**
5207
\brief This function attempts to create a new layer on the dataset with the
5208
indicated name, coordinate system, geometry type.
5209
5210
The papszOptions argument can be used to control driver specific creation
5211
options.  These options are normally documented in the format specific
5212
documentation.
5213
5214
This method is the same as the C++ method GDALDataset::CreateLayer().
5215
5216
Example:
5217
5218
\code{.c}
5219
#include "gdal.h"
5220
#include "cpl_string.h"
5221
5222
...
5223
5224
        OGRLayerH  hLayer;
5225
        char     **papszOptions;
5226
5227
        if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5228
        {
5229
        ...
5230
        }
5231
5232
        papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5233
        hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5234
                                         papszOptions );
5235
        CSLDestroy( papszOptions );
5236
5237
        if( hLayer == NULL )
5238
        {
5239
            ...
5240
        }
5241
\endcode
5242
5243
@since GDAL 2.0
5244
5245
@param hDS the dataset handle
5246
@param pszName the name for the new layer.  This should ideally not
5247
match any existing layer on the datasource.
5248
@param hSpatialRef the coordinate system to use for the new layer, or NULL if
5249
no coordinate system is available.
5250
@param eGType the geometry type for the layer.  Use wkbUnknown if there
5251
are no constraints on the types geometry to be written.
5252
@param papszOptions a StringList of name=value options.  Options are driver
5253
specific.
5254
5255
@return NULL is returned on failure, or a new OGRLayer handle on success.
5256
5257
*/
5258
5259
OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5260
                                 OGRSpatialReferenceH hSpatialRef,
5261
                                 OGRwkbGeometryType eGType,
5262
                                 CSLConstList papszOptions)
5263
5264
0
{
5265
0
    VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5266
5267
0
    if (pszName == nullptr)
5268
0
    {
5269
0
        CPLError(CE_Failure, CPLE_ObjectNull,
5270
0
                 "Name was NULL in GDALDatasetCreateLayer");
5271
0
        return nullptr;
5272
0
    }
5273
5274
0
    OGRLayerH hLayer =
5275
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5276
0
            pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5277
0
            const_cast<char **>(papszOptions)));
5278
5279
0
#ifdef OGRAPISPY_ENABLED
5280
0
    if (bOGRAPISpyEnabled)
5281
0
        OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5282
0
                                 const_cast<char **>(papszOptions), hLayer);
5283
0
#endif
5284
5285
0
    return hLayer;
5286
0
}
5287
5288
/************************************************************************/
5289
/*                 GDALDatasetCreateLayerFromGeomFieldDefn()            */
5290
/************************************************************************/
5291
5292
/**
5293
\brief This function attempts to create a new layer on the dataset with the
5294
indicated name and geometry field.
5295
5296
When poGeomFieldDefn is not null, most drivers should honor
5297
poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5298
Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5299
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5300
poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5301
very few currently.
5302
5303
Note that even if a geometry coordinate precision is set and a driver honors the
5304
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5305
OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5306
with the coordinate precision. That is they are assumed to be valid once their
5307
coordinates are rounded to it. If it might not be the case, the user may set
5308
the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5309
or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5310
the passed geometries.
5311
5312
The papszOptions argument can be used to control driver specific creation
5313
options.  These options are normally documented in the format specific
5314
documentation.
5315
5316
This method is the same as the C++ method GDALDataset::CreateLayer().
5317
5318
@param hDS the dataset handle
5319
@param pszName the name for the new layer.  This should ideally not
5320
match any existing layer on the datasource.
5321
@param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5322
a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5323
for drivers supporting that interface).
5324
@param papszOptions a StringList of name=value options.  Options are driver
5325
specific.
5326
5327
@return NULL is returned on failure, or a new OGRLayer handle on success.
5328
5329
@since GDAL 3.9
5330
5331
*/
5332
5333
OGRLayerH
5334
GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5335
                                        OGRGeomFieldDefnH hGeomFieldDefn,
5336
                                        CSLConstList papszOptions)
5337
5338
0
{
5339
0
    VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5340
5341
0
    if (!pszName)
5342
0
    {
5343
0
        CPLError(CE_Failure, CPLE_ObjectNull,
5344
0
                 "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5345
0
        return nullptr;
5346
0
    }
5347
5348
0
    OGRLayerH hLayer =
5349
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5350
0
            pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5351
0
            papszOptions));
5352
0
    return hLayer;
5353
0
}
5354
5355
/************************************************************************/
5356
/*                         GDALDatasetCopyLayer()                       */
5357
/************************************************************************/
5358
5359
/**
5360
 \brief Duplicate an existing layer.
5361
5362
 This function creates a new layer, duplicate the field definitions of the
5363
 source layer and then duplicate each features of the source layer.
5364
 The papszOptions argument
5365
 can be used to control driver specific creation options.  These options are
5366
 normally documented in the format specific documentation.
5367
 The source layer may come from another dataset.
5368
5369
 This method is the same as the C++ method GDALDataset::CopyLayer()
5370
5371
 @since GDAL 2.0
5372
5373
 @param hDS the dataset handle.
5374
 @param hSrcLayer source layer.
5375
 @param pszNewName the name of the layer to create.
5376
 @param papszOptions a StringList of name=value options.  Options are driver
5377
                     specific.
5378
5379
 @return a handle to the layer, or NULL if an error occurs.
5380
*/
5381
OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5382
                               const char *pszNewName,
5383
                               CSLConstList papszOptions)
5384
5385
0
{
5386
0
    VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5387
0
    VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5388
0
    VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5389
5390
0
    return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5391
0
        OGRLayer::FromHandle(hSrcLayer), pszNewName,
5392
0
        const_cast<char **>(papszOptions)));
5393
0
}
5394
5395
/************************************************************************/
5396
/*                        GDALDatasetExecuteSQL()                       */
5397
/************************************************************************/
5398
5399
/**
5400
 \brief Execute an SQL statement against the data store.
5401
5402
 The result of an SQL query is either NULL for statements that are in error,
5403
 or that have no results set, or an OGRLayer pointer representing a results
5404
 set from the query.  Note that this OGRLayer is in addition to the layers
5405
 in the data store and must be destroyed with
5406
 ReleaseResultSet() before the dataset is closed
5407
 (destroyed).
5408
5409
 This method is the same as the C++ method GDALDataset::ExecuteSQL()
5410
5411
 For more information on the SQL dialect supported internally by OGR
5412
 review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5413
 document.  Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5414
 to the underlying RDBMS.
5415
5416
 Starting with OGR 1.10, the <a
5417
 href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5418
 also be used.
5419
5420
 @since GDAL 2.0
5421
5422
 @param hDS the dataset handle.
5423
 @param pszStatement the SQL statement to execute.
5424
 @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5425
5426
 @param pszDialect allows control of the statement dialect. If set to NULL, the
5427
 OGR SQL engine will be used, except for RDBMS drivers that will use their
5428
 dedicated SQL engine, unless OGRSQL is explicitly passed as the
5429
 dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5430
5431
 @return an OGRLayer containing the results of the query.  Deallocate with
5432
 GDALDatasetReleaseResultSet().
5433
5434
*/
5435
5436
OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5437
                                OGRGeometryH hSpatialFilter,
5438
                                const char *pszDialect)
5439
5440
0
{
5441
0
    VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5442
5443
0
    OGRLayerH hLayer =
5444
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5445
0
            pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5446
5447
0
#ifdef OGRAPISPY_ENABLED
5448
0
    if (bOGRAPISpyEnabled)
5449
0
        OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5450
0
                                hLayer);
5451
0
#endif
5452
5453
0
    return hLayer;
5454
0
}
5455
5456
/************************************************************************/
5457
/*                        GDALDatasetAbortSQL()                         */
5458
/************************************************************************/
5459
5460
/**
5461
 \brief Abort any SQL statement running in the data store.
5462
5463
 This function can be safely called from any thread (pending that the dataset
5464
 object is still alive). Driver implementations will make sure that it can be
5465
 called in a thread-safe way.
5466
5467
 This might not be implemented by all drivers. At time of writing, only SQLite,
5468
 GPKG and PG drivers implement it
5469
5470
 This method is the same as the C++ method GDALDataset::AbortSQL()
5471
5472
 @since GDAL 3.2.0
5473
5474
 @param hDS the dataset handle.
5475
5476
 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5477
 is not supported for this datasource. .
5478
5479
*/
5480
5481
OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5482
5483
0
{
5484
0
    VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5485
0
    return GDALDataset::FromHandle(hDS)->AbortSQL();
5486
0
}
5487
5488
/************************************************************************/
5489
/*                      GDALDatasetGetStyleTable()                      */
5490
/************************************************************************/
5491
5492
/**
5493
 \brief Returns dataset style table.
5494
5495
 This function is the same as the C++ method GDALDataset::GetStyleTable()
5496
5497
 @since GDAL 2.0
5498
5499
 @param hDS the dataset handle
5500
 @return handle to a style table which should not be modified or freed by the
5501
 caller.
5502
*/
5503
5504
OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5505
5506
0
{
5507
0
    VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5508
5509
0
    return reinterpret_cast<OGRStyleTableH>(
5510
0
        GDALDataset::FromHandle(hDS)->GetStyleTable());
5511
0
}
5512
5513
/************************************************************************/
5514
/*                    GDALDatasetSetStyleTableDirectly()                */
5515
/************************************************************************/
5516
5517
/**
5518
 \brief Set dataset style table.
5519
5520
 This function operate exactly as GDALDatasetSetStyleTable() except that it
5521
 assumes ownership of the passed table.
5522
5523
 This function is the same as the C++ method
5524
 GDALDataset::SetStyleTableDirectly()
5525
5526
 @since GDAL 2.0
5527
5528
 @param hDS the dataset handle
5529
 @param hStyleTable style table handle to set
5530
5531
*/
5532
5533
void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5534
                                      OGRStyleTableH hStyleTable)
5535
5536
0
{
5537
0
    VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5538
5539
0
    GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5540
0
        reinterpret_cast<OGRStyleTable *>(hStyleTable));
5541
0
}
5542
5543
/************************************************************************/
5544
/*                     GDALDatasetSetStyleTable()                       */
5545
/************************************************************************/
5546
5547
/**
5548
 \brief Set dataset style table.
5549
5550
 This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5551
 it assumes ownership of the passed table.
5552
5553
 This function is the same as the C++ method GDALDataset::SetStyleTable()
5554
5555
 @since GDAL 2.0
5556
5557
 @param hDS the dataset handle
5558
 @param hStyleTable style table handle to set
5559
5560
*/
5561
5562
void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5563
5564
0
{
5565
0
    VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5566
0
    VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5567
5568
0
    GDALDataset::FromHandle(hDS)->SetStyleTable(
5569
0
        reinterpret_cast<OGRStyleTable *>(hStyleTable));
5570
0
}
5571
5572
/************************************************************************/
5573
/*                    ValidateLayerCreationOptions()                    */
5574
/************************************************************************/
5575
5576
//! @cond Doxygen_Suppress
5577
int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5578
0
{
5579
0
    const char *pszOptionList =
5580
0
        GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5581
0
    if (pszOptionList == nullptr && poDriver != nullptr)
5582
0
    {
5583
0
        pszOptionList =
5584
0
            poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5585
0
    }
5586
0
    CPLString osDataset;
5587
0
    osDataset.Printf("dataset %s", GetDescription());
5588
0
    return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5589
0
                               osDataset);
5590
0
}
5591
5592
//! @endcond
5593
5594
/************************************************************************/
5595
/*                              Release()                               */
5596
/************************************************************************/
5597
5598
/**
5599
\brief Drop a reference to this dataset, and if the reference count drops to one
5600
close (destroy) the dataset.
5601
5602
This method is the same as the C function OGRReleaseDataSource().
5603
5604
@deprecated. In GDAL 2, use GDALClose() instead
5605
5606
@return OGRERR_NONE on success or an error code.
5607
*/
5608
5609
OGRErr GDALDataset::Release()
5610
5611
0
{
5612
0
    ReleaseRef();
5613
0
    return OGRERR_NONE;
5614
0
}
5615
5616
/************************************************************************/
5617
/*                            GetRefCount()                             */
5618
/************************************************************************/
5619
5620
/**
5621
\brief Fetch reference count.
5622
5623
This method is the same as the C function OGR_DS_GetRefCount().
5624
5625
In GDAL 1.X, this method used to be in the OGRDataSource class.
5626
5627
@return the current reference count for the datasource object itself.
5628
*/
5629
5630
int GDALDataset::GetRefCount() const
5631
0
{
5632
0
    return nRefCount;
5633
0
}
5634
5635
/************************************************************************/
5636
/*                         GetSummaryRefCount()                         */
5637
/************************************************************************/
5638
5639
/**
5640
\brief Fetch reference count of datasource and all owned layers.
5641
5642
This method is the same as the C function  OGR_DS_GetSummaryRefCount().
5643
5644
In GDAL 1.X, this method used to be in the OGRDataSource class.
5645
5646
@deprecated
5647
5648
@return the current summary reference count for the datasource and its layers.
5649
*/
5650
5651
int GDALDataset::GetSummaryRefCount() const
5652
5653
0
{
5654
0
    CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5655
0
    int nSummaryCount = nRefCount;
5656
0
    GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5657
5658
0
    for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5659
0
        nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5660
5661
0
    return nSummaryCount;
5662
0
}
5663
5664
/************************************************************************/
5665
/*                           ICreateLayer()                             */
5666
/************************************************************************/
5667
5668
/**
5669
 \brief This method attempts to create a new layer on the dataset with the
5670
 indicated name, coordinate system, geometry type.
5671
5672
 This method is reserved to implementation by drivers.
5673
5674
 The papszOptions argument can be used to control driver specific creation
5675
 options.  These options are normally documented in the format specific
5676
 documentation.
5677
5678
 @param pszName the name for the new layer.  This should ideally not
5679
 match any existing layer on the datasource.
5680
 @param poGeomFieldDefn the geometry field definition to use for the new layer,
5681
 or NULL if there is no geometry field.
5682
 @param papszOptions a StringList of name=value options.  Options are driver
5683
 specific.
5684
5685
 @return NULL is returned on failure, or a new OGRLayer handle on success.
5686
5687
 @since GDAL 2.0 (prototype modified in 3.9)
5688
*/
5689
5690
OGRLayer *
5691
GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5692
                          CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5693
                          CPL_UNUSED CSLConstList papszOptions)
5694
5695
0
{
5696
0
    CPLError(CE_Failure, CPLE_NotSupported,
5697
0
             "CreateLayer() not supported by this dataset.");
5698
5699
0
    return nullptr;
5700
0
}
5701
5702
/************************************************************************/
5703
/*                             CopyLayer()                              */
5704
/************************************************************************/
5705
5706
/**
5707
 \brief Duplicate an existing layer.
5708
5709
 This method creates a new layer, duplicate the field definitions of the
5710
 source layer and then duplicate each features of the source layer.
5711
 The papszOptions argument
5712
 can be used to control driver specific creation options.  These options are
5713
 normally documented in the format specific documentation.
5714
 The source layer may come from another dataset.
5715
5716
 This method is the same as the C function GDALDatasetCopyLayer() and the
5717
 deprecated OGR_DS_CopyLayer().
5718
5719
 In GDAL 1.X, this method used to be in the OGRDataSource class.
5720
5721
 @param poSrcLayer source layer.
5722
 @param pszNewName the name of the layer to create.
5723
 @param papszOptions a StringList of name=value options.  Options are driver
5724
                     specific. There is a common option to set output layer
5725
                     spatial reference: DST_SRSWKT. The option should be in
5726
                     WKT format. Starting with GDAL 3.7, the common option
5727
                     COPY_MD can be set to NO to prevent the default copying
5728
                     of the metadata from the source layer to the target layer.
5729
5730
 @return a handle to the layer, or NULL if an error occurs.
5731
*/
5732
5733
OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
5734
                                 char **papszOptions)
5735
5736
0
{
5737
    /* -------------------------------------------------------------------- */
5738
    /*      Create the layer.                                               */
5739
    /* -------------------------------------------------------------------- */
5740
0
    if (!TestCapability(ODsCCreateLayer))
5741
0
    {
5742
0
        CPLError(CE_Failure, CPLE_NotSupported,
5743
0
                 "This datasource does not support creation of layers.");
5744
0
        return nullptr;
5745
0
    }
5746
5747
0
    const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5748
0
    OGRSpatialReference oDstSpaRef(pszSRSWKT);
5749
0
    oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5750
0
    OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5751
0
    OGRLayer *poDstLayer = nullptr;
5752
5753
0
    CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
5754
0
    aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
5755
0
    aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
5756
5757
0
    CPLErrorReset();
5758
0
    const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5759
0
    if (nSrcGeomFieldCount == 1)
5760
0
    {
5761
0
        OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
5762
0
        if (pszSRSWKT)
5763
0
            oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
5764
0
        poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
5765
0
                                  aosCleanedUpOptions.List());
5766
0
    }
5767
0
    else
5768
0
    {
5769
0
        poDstLayer =
5770
0
            ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
5771
0
    }
5772
5773
0
    if (poDstLayer == nullptr)
5774
0
        return nullptr;
5775
5776
0
    if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
5777
0
    {
5778
0
        char **papszMD = poSrcLayer->GetMetadata();
5779
0
        if (papszMD)
5780
0
            poDstLayer->SetMetadata(papszMD);
5781
0
    }
5782
5783
    /* -------------------------------------------------------------------- */
5784
    /*      Add fields.  Default to copy all fields, and make sure to       */
5785
    /*      establish a mapping between indices, rather than names, in      */
5786
    /*      case the target datasource has altered it (e.g. Shapefile       */
5787
    /*      limited to 10 char field names).                                */
5788
    /* -------------------------------------------------------------------- */
5789
0
    const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5790
5791
    // Initialize the index-to-index map to -1's.
5792
0
    std::vector<int> anMap(nSrcFieldCount, -1);
5793
5794
    // Caution: At the time of writing, the MapInfo driver
5795
    // returns NULL until a field has been added.
5796
0
    OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5797
0
    int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5798
0
    for (int iField = 0; iField < nSrcFieldCount; ++iField)
5799
0
    {
5800
0
        OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5801
0
        OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5802
5803
        // The field may have been already created at layer creation.
5804
0
        int iDstField = -1;
5805
0
        if (poDstFDefn)
5806
0
            iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5807
0
        if (iDstField >= 0)
5808
0
        {
5809
0
            anMap[iField] = iDstField;
5810
0
        }
5811
0
        else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
5812
0
        {
5813
            // Now that we've created a field, GetLayerDefn() won't return NULL.
5814
0
            if (poDstFDefn == nullptr)
5815
0
                poDstFDefn = poDstLayer->GetLayerDefn();
5816
5817
            // Sanity check: if it fails, the driver is buggy.
5818
0
            if (poDstFDefn != nullptr &&
5819
0
                poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5820
0
            {
5821
0
                CPLError(CE_Warning, CPLE_AppDefined,
5822
0
                         "The output driver has claimed to have added the %s "
5823
0
                         "field, but it did not!",
5824
0
                         oFieldDefn.GetNameRef());
5825
0
            }
5826
0
            else
5827
0
            {
5828
0
                anMap[iField] = nDstFieldCount;
5829
0
                ++nDstFieldCount;
5830
0
            }
5831
0
        }
5832
0
    }
5833
5834
    /* -------------------------------------------------------------------- */
5835
0
    std::unique_ptr<OGRCoordinateTransformation> poCT;
5836
0
    OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5837
0
    if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
5838
0
        sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5839
0
    {
5840
0
        poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
5841
0
        if (nullptr == poCT)
5842
0
        {
5843
0
            CPLError(CE_Failure, CPLE_NotSupported,
5844
0
                     "This input/output spatial reference is not supported.");
5845
0
            return nullptr;
5846
0
        }
5847
0
    }
5848
    /* -------------------------------------------------------------------- */
5849
    /*      Create geometry fields.                                         */
5850
    /* -------------------------------------------------------------------- */
5851
0
    if (nSrcGeomFieldCount > 1 &&
5852
0
        TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
5853
0
    {
5854
5855
0
        for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5856
0
        {
5857
0
            if (nullptr == pszSRSWKT)
5858
0
            {
5859
0
                poDstLayer->CreateGeomField(
5860
0
                    poSrcDefn->GetGeomFieldDefn(iField));
5861
0
            }
5862
0
            else
5863
0
            {
5864
0
                OGRGeomFieldDefn *pDstGeomFieldDefn =
5865
0
                    poSrcDefn->GetGeomFieldDefn(iField);
5866
0
                pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
5867
0
                poDstLayer->CreateGeomField(pDstGeomFieldDefn);
5868
0
            }
5869
0
        }
5870
0
    }
5871
5872
    /* -------------------------------------------------------------------- */
5873
    /*      Check if the destination layer supports transactions and set a  */
5874
    /*      default number of features in a single transaction.             */
5875
    /* -------------------------------------------------------------------- */
5876
0
    const int nGroupTransactions =
5877
0
        poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
5878
5879
    /* -------------------------------------------------------------------- */
5880
    /*      Transfer features.                                              */
5881
    /* -------------------------------------------------------------------- */
5882
0
    poSrcLayer->ResetReading();
5883
5884
0
    if (nGroupTransactions <= 0)
5885
0
    {
5886
0
        while (true)
5887
0
        {
5888
0
            auto poFeature =
5889
0
                std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5890
5891
0
            if (poFeature == nullptr)
5892
0
                break;
5893
5894
0
            CPLErrorReset();
5895
0
            auto poDstFeature =
5896
0
                std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5897
5898
0
            if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
5899
0
                OGRERR_NONE)
5900
0
            {
5901
0
                CPLError(CE_Failure, CPLE_AppDefined,
5902
0
                         "Unable to translate feature " CPL_FRMT_GIB
5903
0
                         " from layer %s.",
5904
0
                         poFeature->GetFID(), poSrcDefn->GetName());
5905
0
                return poDstLayer;
5906
0
            }
5907
5908
0
            if (nullptr != poCT)
5909
0
            {
5910
0
                for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5911
0
                {
5912
0
                    OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
5913
0
                    if (nullptr == pGeom)
5914
0
                        continue;
5915
5916
0
                    const OGRErr eErr = pGeom->transform(poCT.get());
5917
0
                    if (eErr == OGRERR_NONE)
5918
0
                        continue;
5919
5920
0
                    CPLError(CE_Failure, CPLE_AppDefined,
5921
0
                             "Unable to transform geometry " CPL_FRMT_GIB
5922
0
                             " from layer %s.",
5923
0
                             poFeature->GetFID(), poSrcDefn->GetName());
5924
0
                    return poDstLayer;
5925
0
                }
5926
0
            }
5927
5928
0
            poDstFeature->SetFID(poFeature->GetFID());
5929
5930
0
            CPLErrorReset();
5931
0
            if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
5932
0
            {
5933
0
                return poDstLayer;
5934
0
            }
5935
0
        }
5936
0
    }
5937
0
    else
5938
0
    {
5939
0
        std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
5940
0
        try
5941
0
        {
5942
0
            apoDstFeatures.resize(nGroupTransactions);
5943
0
        }
5944
0
        catch (const std::exception &e)
5945
0
        {
5946
0
            CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
5947
0
            return poDstLayer;
5948
0
        }
5949
0
        bool bStopTransfer = false;
5950
0
        while (!bStopTransfer)
5951
0
        {
5952
            /* --------------------------------------------------------------------
5953
             */
5954
            /*      Fill the array with features. */
5955
            /* --------------------------------------------------------------------
5956
             */
5957
            // Number of features in the temporary array.
5958
0
            int nFeatCount = 0;  // Used after for.
5959
0
            for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
5960
0
            {
5961
0
                auto poFeature =
5962
0
                    std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5963
5964
0
                if (poFeature == nullptr)
5965
0
                {
5966
0
                    bStopTransfer = true;
5967
0
                    break;
5968
0
                }
5969
5970
0
                CPLErrorReset();
5971
0
                apoDstFeatures[nFeatCount] =
5972
0
                    std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5973
5974
0
                if (apoDstFeatures[nFeatCount]->SetFrom(
5975
0
                        poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
5976
0
                {
5977
0
                    CPLError(CE_Failure, CPLE_AppDefined,
5978
0
                             "Unable to translate feature " CPL_FRMT_GIB
5979
0
                             " from layer %s.",
5980
0
                             poFeature->GetFID(), poSrcDefn->GetName());
5981
0
                    bStopTransfer = true;
5982
0
                    poFeature.reset();
5983
0
                    break;
5984
0
                }
5985
5986
0
                if (nullptr != poCT)
5987
0
                {
5988
0
                    for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5989
0
                    {
5990
0
                        OGRGeometry *pGeom =
5991
0
                            apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
5992
0
                        if (nullptr == pGeom)
5993
0
                            continue;
5994
5995
0
                        const OGRErr eErr = pGeom->transform(poCT.get());
5996
0
                        if (eErr == OGRERR_NONE)
5997
0
                            continue;
5998
5999
0
                        CPLError(CE_Failure, CPLE_AppDefined,
6000
0
                                 "Unable to transform geometry " CPL_FRMT_GIB
6001
0
                                 " from layer %s.",
6002
0
                                 poFeature->GetFID(), poSrcDefn->GetName());
6003
0
                        bStopTransfer = true;
6004
0
                        poFeature.reset();
6005
0
                        break;
6006
0
                    }
6007
0
                }
6008
6009
0
                if (poFeature)
6010
0
                {
6011
0
                    apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
6012
0
                }
6013
0
            }
6014
6015
0
            CPLErrorReset();
6016
0
            bool bStopTransaction = false;
6017
0
            while (!bStopTransaction)
6018
0
            {
6019
0
                bStopTransaction = true;
6020
0
                if (poDstLayer->StartTransaction() != OGRERR_NONE)
6021
0
                    break;
6022
0
                for (int i = 0; i < nFeatCount; ++i)
6023
0
                {
6024
0
                    if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
6025
0
                        OGRERR_NONE)
6026
0
                    {
6027
0
                        bStopTransfer = true;
6028
0
                        bStopTransaction = false;
6029
0
                        break;
6030
0
                    }
6031
0
                    apoDstFeatures[i].reset();
6032
0
                }
6033
0
                if (bStopTransaction)
6034
0
                {
6035
0
                    if (poDstLayer->CommitTransaction() != OGRERR_NONE)
6036
0
                        break;
6037
0
                }
6038
0
                else
6039
0
                {
6040
0
                    poDstLayer->RollbackTransaction();
6041
0
                }
6042
0
            }
6043
0
        }
6044
0
    }
6045
6046
0
    return poDstLayer;
6047
0
}
6048
6049
/************************************************************************/
6050
/*                            DeleteLayer()                             */
6051
/************************************************************************/
6052
6053
/**
6054
 \fn GDALDataset::DeleteLayer(int)
6055
 \brief Delete the indicated layer from the datasource.
6056
6057
 If this method is supported
6058
 the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
6059
6060
 This method is the same as the C function GDALDatasetDeleteLayer() and the
6061
 deprecated OGR_DS_DeleteLayer().
6062
6063
 In GDAL 1.X, this method used to be in the OGRDataSource class.
6064
6065
 @param iLayer the index of the layer to delete.
6066
6067
 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
6068
 layers is not supported for this datasource.
6069
6070
*/
6071
6072
OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
6073
6074
0
{
6075
0
    CPLError(CE_Failure, CPLE_NotSupported,
6076
0
             "DeleteLayer() not supported by this dataset.");
6077
6078
0
    return OGRERR_UNSUPPORTED_OPERATION;
6079
0
}
6080
6081
/************************************************************************/
6082
/*                           GetLayerByName()                           */
6083
/************************************************************************/
6084
6085
/**
6086
 \brief Fetch a layer by name.
6087
6088
 The returned layer remains owned by the
6089
 GDALDataset and should not be deleted by the application.
6090
6091
 This method is the same as the C function GDALDatasetGetLayerByName() and the
6092
 deprecated OGR_DS_GetLayerByName().
6093
6094
 In GDAL 1.X, this method used to be in the OGRDataSource class.
6095
6096
 @param pszName the layer name of the layer to fetch.
6097
6098
 @return the layer, or NULL if Layer is not found or an error occurs.
6099
*/
6100
6101
OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6102
6103
0
{
6104
0
    CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6105
6106
0
    if (!pszName)
6107
0
        return nullptr;
6108
6109
    // First a case sensitive check.
6110
0
    for (int i = 0; i < GetLayerCount(); ++i)
6111
0
    {
6112
0
        OGRLayer *poLayer = GetLayer(i);
6113
6114
0
        if (strcmp(pszName, poLayer->GetName()) == 0)
6115
0
            return poLayer;
6116
0
    }
6117
6118
    // Then case insensitive.
6119
0
    for (int i = 0; i < GetLayerCount(); ++i)
6120
0
    {
6121
0
        OGRLayer *poLayer = GetLayer(i);
6122
6123
0
        if (EQUAL(pszName, poLayer->GetName()))
6124
0
            return poLayer;
6125
0
    }
6126
6127
0
    return nullptr;
6128
0
}
6129
6130
//! @cond Doxygen_Suppress
6131
/************************************************************************/
6132
/*                       ProcessSQLCreateIndex()                        */
6133
/*                                                                      */
6134
/*      The correct syntax for creating an index in our dialect of      */
6135
/*      SQL is:                                                         */
6136
/*                                                                      */
6137
/*        CREATE INDEX ON <layername> USING <columnname>                */
6138
/************************************************************************/
6139
6140
OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6141
6142
0
{
6143
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6144
6145
    /* -------------------------------------------------------------------- */
6146
    /*      Do some general syntax checking.                                */
6147
    /* -------------------------------------------------------------------- */
6148
0
    if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6149
0
        !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6150
0
        !EQUAL(papszTokens[4], "USING"))
6151
0
    {
6152
0
        CSLDestroy(papszTokens);
6153
0
        CPLError(CE_Failure, CPLE_AppDefined,
6154
0
                 "Syntax error in CREATE INDEX command.\n"
6155
0
                 "Was '%s'\n"
6156
0
                 "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6157
0
                 pszSQLCommand);
6158
0
        return OGRERR_FAILURE;
6159
0
    }
6160
6161
    /* -------------------------------------------------------------------- */
6162
    /*      Find the named layer.                                           */
6163
    /* -------------------------------------------------------------------- */
6164
0
    OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6165
0
    if (poLayer == nullptr)
6166
0
    {
6167
0
        CPLError(CE_Failure, CPLE_AppDefined,
6168
0
                 "CREATE INDEX ON failed, no such layer as `%s'.",
6169
0
                 papszTokens[3]);
6170
0
        CSLDestroy(papszTokens);
6171
0
        return OGRERR_FAILURE;
6172
0
    }
6173
6174
    /* -------------------------------------------------------------------- */
6175
    /*      Does this layer even support attribute indexes?                 */
6176
    /* -------------------------------------------------------------------- */
6177
0
    if (poLayer->GetIndex() == nullptr)
6178
0
    {
6179
0
        CPLError(CE_Failure, CPLE_AppDefined,
6180
0
                 "CREATE INDEX ON not supported by this driver.");
6181
0
        CSLDestroy(papszTokens);
6182
0
        return OGRERR_FAILURE;
6183
0
    }
6184
6185
    /* -------------------------------------------------------------------- */
6186
    /*      Find the named field.                                           */
6187
    /* -------------------------------------------------------------------- */
6188
0
    int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6189
6190
0
    CSLDestroy(papszTokens);
6191
6192
0
    if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6193
0
    {
6194
0
        CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6195
0
                 pszSQLCommand);
6196
0
        return OGRERR_FAILURE;
6197
0
    }
6198
6199
    /* -------------------------------------------------------------------- */
6200
    /*      Attempt to create the index.                                    */
6201
    /* -------------------------------------------------------------------- */
6202
0
    OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6203
0
    if (eErr == OGRERR_NONE)
6204
0
    {
6205
0
        eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6206
0
    }
6207
0
    else
6208
0
    {
6209
0
        if (strlen(CPLGetLastErrorMsg()) == 0)
6210
0
            CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6211
0
    }
6212
6213
0
    return eErr;
6214
0
}
6215
6216
/************************************************************************/
6217
/*                        ProcessSQLDropIndex()                         */
6218
/*                                                                      */
6219
/*      The correct syntax for dropping one or more indexes in          */
6220
/*      the OGR SQL dialect is:                                         */
6221
/*                                                                      */
6222
/*          DROP INDEX ON <layername> [USING <columnname>]              */
6223
/************************************************************************/
6224
6225
OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6226
6227
0
{
6228
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6229
6230
    /* -------------------------------------------------------------------- */
6231
    /*      Do some general syntax checking.                                */
6232
    /* -------------------------------------------------------------------- */
6233
0
    if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6234
0
        !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6235
0
        !EQUAL(papszTokens[2], "ON") ||
6236
0
        (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6237
0
    {
6238
0
        CSLDestroy(papszTokens);
6239
0
        CPLError(CE_Failure, CPLE_AppDefined,
6240
0
                 "Syntax error in DROP INDEX command.\n"
6241
0
                 "Was '%s'\n"
6242
0
                 "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6243
0
                 pszSQLCommand);
6244
0
        return OGRERR_FAILURE;
6245
0
    }
6246
6247
    /* -------------------------------------------------------------------- */
6248
    /*      Find the named layer.                                           */
6249
    /* -------------------------------------------------------------------- */
6250
0
    OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6251
0
    if (poLayer == nullptr)
6252
0
    {
6253
0
        CPLError(CE_Failure, CPLE_AppDefined,
6254
0
                 "DROP INDEX ON failed, no such layer as `%s'.",
6255
0
                 papszTokens[3]);
6256
0
        CSLDestroy(papszTokens);
6257
0
        return OGRERR_FAILURE;
6258
0
    }
6259
6260
    /* -------------------------------------------------------------------- */
6261
    /*      Does this layer even support attribute indexes?                 */
6262
    /* -------------------------------------------------------------------- */
6263
0
    if (poLayer->GetIndex() == nullptr)
6264
0
    {
6265
0
        CPLError(CE_Failure, CPLE_AppDefined,
6266
0
                 "Indexes not supported by this driver.");
6267
0
        CSLDestroy(papszTokens);
6268
0
        return OGRERR_FAILURE;
6269
0
    }
6270
6271
    /* -------------------------------------------------------------------- */
6272
    /*      If we were not given a field name, drop all indexes.            */
6273
    /* -------------------------------------------------------------------- */
6274
0
    if (CSLCount(papszTokens) == 4)
6275
0
    {
6276
0
        for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6277
0
        {
6278
0
            OGRAttrIndex *poAttrIndex;
6279
6280
0
            poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6281
0
            if (poAttrIndex != nullptr)
6282
0
            {
6283
0
                const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6284
0
                if (eErr != OGRERR_NONE)
6285
0
                {
6286
0
                    CSLDestroy(papszTokens);
6287
0
                    return eErr;
6288
0
                }
6289
0
            }
6290
0
        }
6291
6292
0
        CSLDestroy(papszTokens);
6293
0
        return OGRERR_NONE;
6294
0
    }
6295
6296
    /* -------------------------------------------------------------------- */
6297
    /*      Find the named field.                                           */
6298
    /* -------------------------------------------------------------------- */
6299
0
    int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6300
0
    CSLDestroy(papszTokens);
6301
6302
0
    if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6303
0
    {
6304
0
        CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6305
0
                 pszSQLCommand);
6306
0
        return OGRERR_FAILURE;
6307
0
    }
6308
6309
    /* -------------------------------------------------------------------- */
6310
    /*      Attempt to drop the index.                                      */
6311
    /* -------------------------------------------------------------------- */
6312
0
    const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6313
6314
0
    return eErr;
6315
0
}
6316
6317
/************************************************************************/
6318
/*                        ProcessSQLDropTable()                         */
6319
/*                                                                      */
6320
/*      The correct syntax for dropping a table (layer) in the OGR SQL  */
6321
/*      dialect is:                                                     */
6322
/*                                                                      */
6323
/*          DROP TABLE <layername>                                      */
6324
/************************************************************************/
6325
6326
OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6327
6328
0
{
6329
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6330
6331
    /* -------------------------------------------------------------------- */
6332
    /*      Do some general syntax checking.                                */
6333
    /* -------------------------------------------------------------------- */
6334
0
    if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6335
0
        !EQUAL(papszTokens[1], "TABLE"))
6336
0
    {
6337
0
        CSLDestroy(papszTokens);
6338
0
        CPLError(CE_Failure, CPLE_AppDefined,
6339
0
                 "Syntax error in DROP TABLE command.\n"
6340
0
                 "Was '%s'\n"
6341
0
                 "Should be of form 'DROP TABLE <table>'",
6342
0
                 pszSQLCommand);
6343
0
        return OGRERR_FAILURE;
6344
0
    }
6345
6346
    /* -------------------------------------------------------------------- */
6347
    /*      Find the named layer.                                           */
6348
    /* -------------------------------------------------------------------- */
6349
0
    OGRLayer *poLayer = nullptr;
6350
6351
0
    int i = 0;  // Used after for.
6352
0
    for (; i < GetLayerCount(); ++i)
6353
0
    {
6354
0
        poLayer = GetLayer(i);
6355
6356
0
        if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6357
0
            break;
6358
0
        poLayer = nullptr;
6359
0
    }
6360
6361
0
    if (poLayer == nullptr)
6362
0
    {
6363
0
        CPLError(CE_Failure, CPLE_AppDefined,
6364
0
                 "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6365
0
        CSLDestroy(papszTokens);
6366
0
        return OGRERR_FAILURE;
6367
0
    }
6368
6369
0
    CSLDestroy(papszTokens);
6370
6371
    /* -------------------------------------------------------------------- */
6372
    /*      Delete it.                                                      */
6373
    /* -------------------------------------------------------------------- */
6374
6375
0
    return DeleteLayer(i);
6376
0
}
6377
6378
//! @endcond
6379
6380
/************************************************************************/
6381
/*                    GDALDatasetParseSQLType()                       */
6382
/************************************************************************/
6383
6384
/* All arguments will be altered */
6385
static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6386
                                            int &nPrecision)
6387
0
{
6388
0
    char *pszParenthesis = strchr(pszType, '(');
6389
0
    if (pszParenthesis)
6390
0
    {
6391
0
        nWidth = atoi(pszParenthesis + 1);
6392
0
        *pszParenthesis = '\0';
6393
0
        char *pszComma = strchr(pszParenthesis + 1, ',');
6394
0
        if (pszComma)
6395
0
            nPrecision = atoi(pszComma + 1);
6396
0
    }
6397
6398
0
    OGRFieldType eType = OFTString;
6399
0
    if (EQUAL(pszType, "INTEGER"))
6400
0
        eType = OFTInteger;
6401
0
    else if (EQUAL(pszType, "INTEGER[]"))
6402
0
        eType = OFTIntegerList;
6403
0
    else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6404
0
             EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6405
0
             EQUAL(pszType, "REAL") /* unofficial alias */)
6406
0
        eType = OFTReal;
6407
0
    else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6408
0
             EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6409
0
             EQUAL(pszType, "REAL[]") /* unofficial alias */)
6410
0
        eType = OFTRealList;
6411
0
    else if (EQUAL(pszType, "CHARACTER") ||
6412
0
             EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6413
0
             EQUAL(pszType, "STRING") /* unofficial alias */ ||
6414
0
             EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6415
0
        eType = OFTString;
6416
0
    else if (EQUAL(pszType, "TEXT[]") ||
6417
0
             EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6418
0
             EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6419
0
        eType = OFTStringList;
6420
0
    else if (EQUAL(pszType, "DATE"))
6421
0
        eType = OFTDate;
6422
0
    else if (EQUAL(pszType, "TIME"))
6423
0
        eType = OFTTime;
6424
0
    else if (EQUAL(pszType, "TIMESTAMP") ||
6425
0
             EQUAL(pszType, "DATETIME") /* unofficial alias */)
6426
0
        eType = OFTDateTime;
6427
0
    else
6428
0
        CPLError(CE_Warning, CPLE_NotSupported,
6429
0
                 "Unsupported column type '%s'. Defaulting to VARCHAR",
6430
0
                 pszType);
6431
6432
0
    return eType;
6433
0
}
6434
6435
/************************************************************************/
6436
/*                    ProcessSQLAlterTableAddColumn()                   */
6437
/*                                                                      */
6438
/*      The correct syntax for adding a column in the OGR SQL           */
6439
/*      dialect is:                                                     */
6440
/*                                                                      */
6441
/*       ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6442
/************************************************************************/
6443
6444
//! @cond Doxygen_Suppress
6445
OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6446
6447
0
{
6448
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6449
6450
    /* -------------------------------------------------------------------- */
6451
    /*      Do some general syntax checking.                                */
6452
    /* -------------------------------------------------------------------- */
6453
0
    const char *pszLayerName = nullptr;
6454
0
    const char *pszColumnName = nullptr;
6455
0
    int iTypeIndex = 0;
6456
0
    const int nTokens = CSLCount(papszTokens);
6457
6458
0
    if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6459
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6460
0
        EQUAL(papszTokens[4], "COLUMN"))
6461
0
    {
6462
0
        pszLayerName = papszTokens[2];
6463
0
        pszColumnName = papszTokens[5];
6464
0
        iTypeIndex = 6;
6465
0
    }
6466
0
    else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6467
0
             EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6468
0
    {
6469
0
        pszLayerName = papszTokens[2];
6470
0
        pszColumnName = papszTokens[4];
6471
0
        iTypeIndex = 5;
6472
0
    }
6473
0
    else
6474
0
    {
6475
0
        CSLDestroy(papszTokens);
6476
0
        CPLError(CE_Failure, CPLE_AppDefined,
6477
0
                 "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6478
0
                 "Was '%s'\n"
6479
0
                 "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6480
0
                 "<columnname> <columntype>'",
6481
0
                 pszSQLCommand);
6482
0
        return OGRERR_FAILURE;
6483
0
    }
6484
6485
    /* -------------------------------------------------------------------- */
6486
    /*      Merge type components into a single string if there were split  */
6487
    /*      with spaces                                                     */
6488
    /* -------------------------------------------------------------------- */
6489
0
    CPLString osType;
6490
0
    for (int i = iTypeIndex; i < nTokens; ++i)
6491
0
    {
6492
0
        osType += papszTokens[i];
6493
0
        CPLFree(papszTokens[i]);
6494
0
    }
6495
0
    char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6496
0
    papszTokens[iTypeIndex + 1] = nullptr;
6497
6498
    /* -------------------------------------------------------------------- */
6499
    /*      Find the named layer.                                           */
6500
    /* -------------------------------------------------------------------- */
6501
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6502
0
    if (poLayer == nullptr)
6503
0
    {
6504
0
        CPLError(CE_Failure, CPLE_AppDefined,
6505
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6506
0
                 pszLayerName);
6507
0
        CSLDestroy(papszTokens);
6508
0
        return OGRERR_FAILURE;
6509
0
    }
6510
6511
    /* -------------------------------------------------------------------- */
6512
    /*      Add column.                                                     */
6513
    /* -------------------------------------------------------------------- */
6514
6515
0
    int nWidth = 0;
6516
0
    int nPrecision = 0;
6517
0
    OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6518
0
    OGRFieldDefn oFieldDefn(pszColumnName, eType);
6519
0
    oFieldDefn.SetWidth(nWidth);
6520
0
    oFieldDefn.SetPrecision(nPrecision);
6521
6522
0
    CSLDestroy(papszTokens);
6523
6524
0
    return poLayer->CreateField(&oFieldDefn);
6525
0
}
6526
6527
/************************************************************************/
6528
/*                    ProcessSQLAlterTableDropColumn()                  */
6529
/*                                                                      */
6530
/*      The correct syntax for dropping a column in the OGR SQL         */
6531
/*      dialect is:                                                     */
6532
/*                                                                      */
6533
/*          ALTER TABLE <layername> DROP [COLUMN] <columnname>          */
6534
/************************************************************************/
6535
6536
OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6537
6538
0
{
6539
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6540
6541
    /* -------------------------------------------------------------------- */
6542
    /*      Do some general syntax checking.                                */
6543
    /* -------------------------------------------------------------------- */
6544
0
    const char *pszLayerName = nullptr;
6545
0
    const char *pszColumnName = nullptr;
6546
0
    if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6547
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6548
0
        EQUAL(papszTokens[4], "COLUMN"))
6549
0
    {
6550
0
        pszLayerName = papszTokens[2];
6551
0
        pszColumnName = papszTokens[5];
6552
0
    }
6553
0
    else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6554
0
             EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6555
0
    {
6556
0
        pszLayerName = papszTokens[2];
6557
0
        pszColumnName = papszTokens[4];
6558
0
    }
6559
0
    else
6560
0
    {
6561
0
        CSLDestroy(papszTokens);
6562
0
        CPLError(CE_Failure, CPLE_AppDefined,
6563
0
                 "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6564
0
                 "Was '%s'\n"
6565
0
                 "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6566
0
                 "<columnname>'",
6567
0
                 pszSQLCommand);
6568
0
        return OGRERR_FAILURE;
6569
0
    }
6570
6571
    /* -------------------------------------------------------------------- */
6572
    /*      Find the named layer.                                           */
6573
    /* -------------------------------------------------------------------- */
6574
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6575
0
    if (poLayer == nullptr)
6576
0
    {
6577
0
        CPLError(CE_Failure, CPLE_AppDefined,
6578
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6579
0
                 pszLayerName);
6580
0
        CSLDestroy(papszTokens);
6581
0
        return OGRERR_FAILURE;
6582
0
    }
6583
6584
    /* -------------------------------------------------------------------- */
6585
    /*      Find the field.                                                 */
6586
    /* -------------------------------------------------------------------- */
6587
6588
0
    int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6589
0
    if (nFieldIndex < 0)
6590
0
    {
6591
0
        CPLError(CE_Failure, CPLE_AppDefined,
6592
0
                 "%s failed, no such field as `%s'.", pszSQLCommand,
6593
0
                 pszColumnName);
6594
0
        CSLDestroy(papszTokens);
6595
0
        return OGRERR_FAILURE;
6596
0
    }
6597
6598
    /* -------------------------------------------------------------------- */
6599
    /*      Remove it.                                                      */
6600
    /* -------------------------------------------------------------------- */
6601
6602
0
    CSLDestroy(papszTokens);
6603
6604
0
    return poLayer->DeleteField(nFieldIndex);
6605
0
}
6606
6607
/************************************************************************/
6608
/*                 ProcessSQLAlterTableRenameColumn()                   */
6609
/*                                                                      */
6610
/*      The correct syntax for renaming a column in the OGR SQL         */
6611
/*      dialect is:                                                     */
6612
/*                                                                      */
6613
/*       ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6614
/************************************************************************/
6615
6616
OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6617
6618
0
{
6619
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6620
6621
    /* -------------------------------------------------------------------- */
6622
    /*      Do some general syntax checking.                                */
6623
    /* -------------------------------------------------------------------- */
6624
0
    const char *pszLayerName = nullptr;
6625
0
    const char *pszOldColName = nullptr;
6626
0
    const char *pszNewColName = nullptr;
6627
0
    if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6628
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6629
0
        EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6630
0
    {
6631
0
        pszLayerName = papszTokens[2];
6632
0
        pszOldColName = papszTokens[5];
6633
0
        pszNewColName = papszTokens[7];
6634
0
    }
6635
0
    else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6636
0
             EQUAL(papszTokens[1], "TABLE") &&
6637
0
             EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6638
0
    {
6639
0
        pszLayerName = papszTokens[2];
6640
0
        pszOldColName = papszTokens[4];
6641
0
        pszNewColName = papszTokens[6];
6642
0
    }
6643
0
    else
6644
0
    {
6645
0
        CSLDestroy(papszTokens);
6646
0
        CPLError(CE_Failure, CPLE_AppDefined,
6647
0
                 "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6648
0
                 "Was '%s'\n"
6649
0
                 "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6650
0
                 "<columnname> TO <newname>'",
6651
0
                 pszSQLCommand);
6652
0
        return OGRERR_FAILURE;
6653
0
    }
6654
6655
    /* -------------------------------------------------------------------- */
6656
    /*      Find the named layer.                                           */
6657
    /* -------------------------------------------------------------------- */
6658
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6659
0
    if (poLayer == nullptr)
6660
0
    {
6661
0
        CPLError(CE_Failure, CPLE_AppDefined,
6662
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6663
0
                 pszLayerName);
6664
0
        CSLDestroy(papszTokens);
6665
0
        return OGRERR_FAILURE;
6666
0
    }
6667
6668
    /* -------------------------------------------------------------------- */
6669
    /*      Find the field.                                                 */
6670
    /* -------------------------------------------------------------------- */
6671
6672
0
    const int nFieldIndex =
6673
0
        poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6674
0
    if (nFieldIndex < 0)
6675
0
    {
6676
0
        CPLError(CE_Failure, CPLE_AppDefined,
6677
0
                 "%s failed, no such field as `%s'.", pszSQLCommand,
6678
0
                 pszOldColName);
6679
0
        CSLDestroy(papszTokens);
6680
0
        return OGRERR_FAILURE;
6681
0
    }
6682
6683
    /* -------------------------------------------------------------------- */
6684
    /*      Rename column.                                                  */
6685
    /* -------------------------------------------------------------------- */
6686
0
    OGRFieldDefn *poOldFieldDefn =
6687
0
        poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6688
0
    OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6689
0
    oNewFieldDefn.SetName(pszNewColName);
6690
6691
0
    CSLDestroy(papszTokens);
6692
6693
0
    return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6694
0
                                   ALTER_NAME_FLAG);
6695
0
}
6696
6697
/************************************************************************/
6698
/*                 ProcessSQLAlterTableAlterColumn()                    */
6699
/*                                                                      */
6700
/*      The correct syntax for altering the type of a column in the     */
6701
/*      OGR SQL dialect is:                                             */
6702
/*                                                                      */
6703
/*   ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6704
/************************************************************************/
6705
6706
OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
6707
6708
0
{
6709
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6710
6711
    /* -------------------------------------------------------------------- */
6712
    /*      Do some general syntax checking.                                */
6713
    /* -------------------------------------------------------------------- */
6714
0
    const char *pszLayerName = nullptr;
6715
0
    const char *pszColumnName = nullptr;
6716
0
    int iTypeIndex = 0;
6717
0
    const int nTokens = CSLCount(papszTokens);
6718
6719
0
    if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
6720
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6721
0
        EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
6722
0
    {
6723
0
        pszLayerName = papszTokens[2];
6724
0
        pszColumnName = papszTokens[5];
6725
0
        iTypeIndex = 7;
6726
0
    }
6727
0
    else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6728
0
             EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6729
0
             EQUAL(papszTokens[5], "TYPE"))
6730
0
    {
6731
0
        pszLayerName = papszTokens[2];
6732
0
        pszColumnName = papszTokens[4];
6733
0
        iTypeIndex = 6;
6734
0
    }
6735
0
    else
6736
0
    {
6737
0
        CSLDestroy(papszTokens);
6738
0
        CPLError(CE_Failure, CPLE_AppDefined,
6739
0
                 "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6740
0
                 "Was '%s'\n"
6741
0
                 "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6742
0
                 "<columnname> TYPE <columntype>'",
6743
0
                 pszSQLCommand);
6744
0
        return OGRERR_FAILURE;
6745
0
    }
6746
6747
    /* -------------------------------------------------------------------- */
6748
    /*      Merge type components into a single string if there were split  */
6749
    /*      with spaces                                                     */
6750
    /* -------------------------------------------------------------------- */
6751
0
    CPLString osType;
6752
0
    for (int i = iTypeIndex; i < nTokens; ++i)
6753
0
    {
6754
0
        osType += papszTokens[i];
6755
0
        CPLFree(papszTokens[i]);
6756
0
    }
6757
0
    char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6758
0
    papszTokens[iTypeIndex + 1] = nullptr;
6759
6760
    /* -------------------------------------------------------------------- */
6761
    /*      Find the named layer.                                           */
6762
    /* -------------------------------------------------------------------- */
6763
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6764
0
    if (poLayer == nullptr)
6765
0
    {
6766
0
        CPLError(CE_Failure, CPLE_AppDefined,
6767
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6768
0
                 pszLayerName);
6769
0
        CSLDestroy(papszTokens);
6770
0
        return OGRERR_FAILURE;
6771
0
    }
6772
6773
    /* -------------------------------------------------------------------- */
6774
    /*      Find the field.                                                 */
6775
    /* -------------------------------------------------------------------- */
6776
6777
0
    const int nFieldIndex =
6778
0
        poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6779
0
    if (nFieldIndex < 0)
6780
0
    {
6781
0
        CPLError(CE_Failure, CPLE_AppDefined,
6782
0
                 "%s failed, no such field as `%s'.", pszSQLCommand,
6783
0
                 pszColumnName);
6784
0
        CSLDestroy(papszTokens);
6785
0
        return OGRERR_FAILURE;
6786
0
    }
6787
6788
    /* -------------------------------------------------------------------- */
6789
    /*      Alter column.                                                   */
6790
    /* -------------------------------------------------------------------- */
6791
6792
0
    OGRFieldDefn *poOldFieldDefn =
6793
0
        poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6794
0
    OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6795
6796
0
    int nWidth = 0;
6797
0
    int nPrecision = 0;
6798
0
    OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6799
0
    oNewFieldDefn.SetType(eType);
6800
0
    oNewFieldDefn.SetWidth(nWidth);
6801
0
    oNewFieldDefn.SetPrecision(nPrecision);
6802
6803
0
    int l_nFlags = 0;
6804
0
    if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6805
0
        l_nFlags |= ALTER_TYPE_FLAG;
6806
0
    if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6807
0
        poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6808
0
        l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6809
6810
0
    CSLDestroy(papszTokens);
6811
6812
0
    if (l_nFlags == 0)
6813
0
        return OGRERR_NONE;
6814
6815
0
    return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6816
0
}
6817
6818
//! @endcond
6819
6820
/************************************************************************/
6821
/*                             ExecuteSQL()                             */
6822
/************************************************************************/
6823
6824
/**
6825
 \brief Execute an SQL statement against the data store.
6826
6827
 The result of an SQL query is either NULL for statements that are in error,
6828
 or that have no results set, or an OGRLayer pointer representing a results
6829
 set from the query.  Note that this OGRLayer is in addition to the layers
6830
 in the data store and must be destroyed with
6831
 ReleaseResultSet() before the dataset is closed
6832
 (destroyed).
6833
6834
 This method is the same as the C function GDALDatasetExecuteSQL() and the
6835
 deprecated OGR_DS_ExecuteSQL().
6836
6837
 For more information on the SQL dialect supported internally by OGR
6838
 review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
6839
 document.  Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
6840
 to the underlying RDBMS.
6841
6842
 Starting with OGR 1.10, the <a
6843
 href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
6844
 also be used.
6845
6846
 In GDAL 1.X, this method used to be in the OGRDataSource class.
6847
6848
 @param pszStatement the SQL statement to execute.
6849
 @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6850
 @param pszDialect allows control of the statement dialect. If set to NULL, the
6851
 OGR SQL engine will be used, except for RDBMS drivers that will use their
6852
 dedicated SQL engine, unless OGRSQL is explicitly passed as the
6853
 dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
6854
6855
 @return an OGRLayer containing the results of the query.  Deallocate with
6856
 ReleaseResultSet().
6857
6858
*/
6859
6860
OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
6861
                                  OGRGeometry *poSpatialFilter,
6862
                                  const char *pszDialect)
6863
6864
0
{
6865
0
    return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
6866
0
}
6867
6868
//! @cond Doxygen_Suppress
6869
OGRLayer *
6870
GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
6871
                        const char *pszDialect,
6872
                        swq_select_parse_options *poSelectParseOptions)
6873
6874
0
{
6875
0
    if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
6876
0
    {
6877
#ifdef SQLITE_ENABLED
6878
        return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
6879
                                   pszDialect);
6880
#else
6881
0
        CPLError(CE_Failure, CPLE_NotSupported,
6882
0
                 "The SQLite driver needs to be compiled to support the "
6883
0
                 "SQLite SQL dialect");
6884
0
        return nullptr;
6885
0
#endif
6886
0
    }
6887
6888
0
    if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
6889
0
        !EQUAL(pszDialect, "OGRSQL"))
6890
0
    {
6891
0
        std::string osDialectList = "'OGRSQL'";
6892
#ifdef SQLITE_ENABLED
6893
        osDialectList += ", 'SQLITE'";
6894
#endif
6895
0
        const char *pszDialects =
6896
0
            GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
6897
0
        if (pszDialects)
6898
0
        {
6899
0
            const CPLStringList aosTokens(
6900
0
                CSLTokenizeString2(pszDialects, " ", 0));
6901
0
            for (int i = 0; i < aosTokens.size(); ++i)
6902
0
            {
6903
0
                if (!EQUAL(aosTokens[i], "OGRSQL") &&
6904
0
                    !EQUAL(aosTokens[i], "SQLITE"))
6905
0
                {
6906
0
                    osDialectList += ", '";
6907
0
                    osDialectList += aosTokens[i];
6908
0
                    osDialectList += "'";
6909
0
                }
6910
0
            }
6911
0
        }
6912
0
        CPLError(CE_Warning, CPLE_NotSupported,
6913
0
                 "Dialect '%s' is unsupported. Only supported dialects are %s. "
6914
0
                 "Defaulting to OGRSQL",
6915
0
                 pszDialect, osDialectList.c_str());
6916
0
    }
6917
6918
    /* -------------------------------------------------------------------- */
6919
    /*      Handle CREATE INDEX statements specially.                       */
6920
    /* -------------------------------------------------------------------- */
6921
0
    if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
6922
0
    {
6923
0
        ProcessSQLCreateIndex(pszStatement);
6924
0
        return nullptr;
6925
0
    }
6926
6927
    /* -------------------------------------------------------------------- */
6928
    /*      Handle DROP INDEX statements specially.                         */
6929
    /* -------------------------------------------------------------------- */
6930
0
    if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
6931
0
    {
6932
0
        ProcessSQLDropIndex(pszStatement);
6933
0
        return nullptr;
6934
0
    }
6935
6936
    /* -------------------------------------------------------------------- */
6937
    /*      Handle DROP TABLE statements specially.                         */
6938
    /* -------------------------------------------------------------------- */
6939
0
    if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
6940
0
    {
6941
0
        ProcessSQLDropTable(pszStatement);
6942
0
        return nullptr;
6943
0
    }
6944
6945
    /* -------------------------------------------------------------------- */
6946
    /*      Handle ALTER TABLE statements specially.                        */
6947
    /* -------------------------------------------------------------------- */
6948
0
    if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
6949
0
    {
6950
0
        char **papszTokens = CSLTokenizeString(pszStatement);
6951
0
        const int nTokens = CSLCount(papszTokens);
6952
0
        if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
6953
0
        {
6954
0
            ProcessSQLAlterTableAddColumn(pszStatement);
6955
0
            CSLDestroy(papszTokens);
6956
0
            return nullptr;
6957
0
        }
6958
0
        else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
6959
0
        {
6960
0
            ProcessSQLAlterTableDropColumn(pszStatement);
6961
0
            CSLDestroy(papszTokens);
6962
0
            return nullptr;
6963
0
        }
6964
0
        else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
6965
0
                 EQUAL(papszTokens[4], "TO"))
6966
0
        {
6967
0
            const char *pszSrcTableName = papszTokens[2];
6968
0
            const char *pszDstTableName = papszTokens[5];
6969
0
            auto poSrcLayer = GetLayerByName(pszSrcTableName);
6970
0
            if (poSrcLayer)
6971
0
            {
6972
0
                CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
6973
0
            }
6974
0
            else
6975
0
            {
6976
0
                CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
6977
0
            }
6978
0
            CSLDestroy(papszTokens);
6979
0
            return nullptr;
6980
0
        }
6981
0
        else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
6982
0
        {
6983
0
            ProcessSQLAlterTableRenameColumn(pszStatement);
6984
0
            CSLDestroy(papszTokens);
6985
0
            return nullptr;
6986
0
        }
6987
0
        else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
6988
0
        {
6989
0
            ProcessSQLAlterTableAlterColumn(pszStatement);
6990
0
            CSLDestroy(papszTokens);
6991
0
            return nullptr;
6992
0
        }
6993
0
        else
6994
0
        {
6995
0
            CPLError(CE_Failure, CPLE_AppDefined,
6996
0
                     "Unsupported ALTER TABLE command : %s", pszStatement);
6997
0
            CSLDestroy(papszTokens);
6998
0
            return nullptr;
6999
0
        }
7000
0
    }
7001
7002
    /* -------------------------------------------------------------------- */
7003
    /*      Preparse the SQL statement.                                     */
7004
    /* -------------------------------------------------------------------- */
7005
0
    swq_select *psSelectInfo = new swq_select();
7006
0
    swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
7007
0
    if (poSelectParseOptions != nullptr)
7008
0
        poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
7009
0
    if (psSelectInfo->preparse(pszStatement,
7010
0
                               poCustomFuncRegistrar != nullptr) != CE_None)
7011
0
    {
7012
0
        delete psSelectInfo;
7013
0
        return nullptr;
7014
0
    }
7015
7016
    /* -------------------------------------------------------------------- */
7017
    /*      If there is no UNION ALL, build result layer.                   */
7018
    /* -------------------------------------------------------------------- */
7019
0
    if (psSelectInfo->poOtherSelect == nullptr)
7020
0
    {
7021
0
        return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
7022
0
                                        pszDialect, poSelectParseOptions);
7023
0
    }
7024
7025
    /* -------------------------------------------------------------------- */
7026
    /*      Build result union layer.                                       */
7027
    /* -------------------------------------------------------------------- */
7028
0
    int nSrcLayers = 0;
7029
0
    OGRLayer **papoSrcLayers = nullptr;
7030
7031
0
    do
7032
0
    {
7033
0
        swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
7034
0
        psSelectInfo->poOtherSelect = nullptr;
7035
7036
0
        OGRLayer *poLayer = BuildLayerFromSelectInfo(
7037
0
            psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
7038
0
        if (poLayer == nullptr)
7039
0
        {
7040
            // Each source layer owns an independent select info.
7041
0
            for (int i = 0; i < nSrcLayers; ++i)
7042
0
                delete papoSrcLayers[i];
7043
0
            CPLFree(papoSrcLayers);
7044
7045
            // So we just have to destroy the remaining select info.
7046
0
            delete psNextSelectInfo;
7047
7048
0
            return nullptr;
7049
0
        }
7050
0
        else
7051
0
        {
7052
0
            papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
7053
0
                papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
7054
0
            papoSrcLayers[nSrcLayers] = poLayer;
7055
0
            ++nSrcLayers;
7056
7057
0
            psSelectInfo = psNextSelectInfo;
7058
0
        }
7059
0
    } while (psSelectInfo != nullptr);
7060
7061
0
    return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
7062
0
}
7063
7064
//! @endcond
7065
7066
/************************************************************************/
7067
/*                             AbortSQL()                             */
7068
/************************************************************************/
7069
7070
/**
7071
 \brief Abort any SQL statement running in the data store.
7072
7073
 This function can be safely called from any thread (pending that the dataset
7074
 object is still alive). Driver implementations will make sure that it can be
7075
 called in a thread-safe way.
7076
7077
 This might not be implemented by all drivers. At time of writing, only SQLite,
7078
 GPKG and PG drivers implement it
7079
7080
 This method is the same as the C method GDALDatasetAbortSQL()
7081
7082
 @since GDAL 3.2.0
7083
7084
7085
*/
7086
7087
OGRErr GDALDataset::AbortSQL()
7088
0
{
7089
0
    CPLError(CE_Failure, CPLE_NotSupported,
7090
0
             "AbortSQL is not supported for this driver.");
7091
0
    return OGRERR_UNSUPPORTED_OPERATION;
7092
0
}
7093
7094
/************************************************************************/
7095
/*                        BuildLayerFromSelectInfo()                    */
7096
/************************************************************************/
7097
7098
struct GDALSQLParseInfo
7099
{
7100
    swq_field_list sFieldList;
7101
    int nExtraDSCount;
7102
    GDALDataset **papoExtraDS;
7103
    char *pszWHERE;
7104
};
7105
7106
OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7107
    swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7108
    const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7109
0
{
7110
0
    std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
7111
7112
0
    std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7113
0
    GDALSQLParseInfo *psParseInfo =
7114
0
        BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
7115
7116
0
    if (psParseInfo)
7117
0
    {
7118
0
        const auto nErrorCounter = CPLGetErrorCounter();
7119
0
        poResults = std::make_unique<OGRGenSQLResultsLayer>(
7120
0
            this, std::move(psSelectInfoUnique), poSpatialFilter,
7121
0
            psParseInfo->pszWHERE, pszDialect);
7122
0
        if (CPLGetErrorCounter() > nErrorCounter &&
7123
0
            CPLGetLastErrorType() != CE_None)
7124
0
            poResults.reset();
7125
0
    }
7126
7127
0
    DestroyParseInfo(psParseInfo);
7128
7129
0
    return poResults.release();
7130
0
}
7131
7132
/************************************************************************/
7133
/*                             DestroyParseInfo()                       */
7134
/************************************************************************/
7135
7136
//! @cond Doxygen_Suppress
7137
void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7138
0
{
7139
0
    if (psParseInfo == nullptr)
7140
0
        return;
7141
7142
0
    CPLFree(psParseInfo->sFieldList.names);
7143
0
    CPLFree(psParseInfo->sFieldList.types);
7144
0
    CPLFree(psParseInfo->sFieldList.table_ids);
7145
0
    CPLFree(psParseInfo->sFieldList.ids);
7146
7147
    // Release the datasets we have opened with OGROpenShared()
7148
    // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7149
    // has taken a reference on them, which it will release in its
7150
    // destructor.
7151
0
    for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7152
0
        GDALClose(psParseInfo->papoExtraDS[iEDS]);
7153
7154
0
    CPLFree(psParseInfo->papoExtraDS);
7155
0
    CPLFree(psParseInfo->pszWHERE);
7156
0
    CPLFree(psParseInfo);
7157
0
}
7158
7159
/************************************************************************/
7160
/*                            BuildParseInfo()                          */
7161
/************************************************************************/
7162
7163
GDALSQLParseInfo *
7164
GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7165
                            swq_select_parse_options *poSelectParseOptions)
7166
0
{
7167
0
    int nFirstLayerFirstSpecialFieldIndex = 0;
7168
7169
0
    GDALSQLParseInfo *psParseInfo =
7170
0
        static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7171
7172
    /* -------------------------------------------------------------------- */
7173
    /*      Validate that all the source tables are recognized, count       */
7174
    /*      fields.                                                         */
7175
    /* -------------------------------------------------------------------- */
7176
0
    int nFieldCount = 0;
7177
7178
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7179
0
    {
7180
0
        swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7181
0
        GDALDataset *poTableDS = this;
7182
7183
0
        if (psTableDef->data_source != nullptr)
7184
0
        {
7185
0
            poTableDS = GDALDataset::FromHandle(
7186
0
                OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7187
0
            if (poTableDS == nullptr)
7188
0
            {
7189
0
                if (strlen(CPLGetLastErrorMsg()) == 0)
7190
0
                    CPLError(CE_Failure, CPLE_AppDefined,
7191
0
                             "Unable to open secondary datasource "
7192
0
                             "`%s' required by JOIN.",
7193
0
                             psTableDef->data_source);
7194
7195
0
                DestroyParseInfo(psParseInfo);
7196
0
                return nullptr;
7197
0
            }
7198
7199
            // Keep in an array to release at the end of this function.
7200
0
            psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7201
0
                psParseInfo->papoExtraDS,
7202
0
                sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7203
0
            psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7204
0
        }
7205
7206
0
        OGRLayer *poSrcLayer =
7207
0
            poTableDS->GetLayerByName(psTableDef->table_name);
7208
7209
0
        if (poSrcLayer == nullptr)
7210
0
        {
7211
0
            CPLError(CE_Failure, CPLE_AppDefined,
7212
0
                     "SELECT from table %s failed, no such table/featureclass.",
7213
0
                     psTableDef->table_name);
7214
7215
0
            DestroyParseInfo(psParseInfo);
7216
0
            return nullptr;
7217
0
        }
7218
7219
0
        nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7220
0
        if (iTable == 0 ||
7221
0
            (poSelectParseOptions &&
7222
0
             poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7223
0
            nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7224
7225
0
        const char *pszFID = poSrcLayer->GetFIDColumn();
7226
0
        if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7227
0
            poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7228
0
            nFieldCount++;
7229
0
    }
7230
7231
    /* -------------------------------------------------------------------- */
7232
    /*      Build the field list for all indicated tables.                  */
7233
    /* -------------------------------------------------------------------- */
7234
7235
0
    psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7236
0
    psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7237
7238
0
    psParseInfo->sFieldList.count = 0;
7239
0
    psParseInfo->sFieldList.names = static_cast<char **>(
7240
0
        CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7241
0
    psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7242
0
        sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7243
0
    psParseInfo->sFieldList.table_ids = static_cast<int *>(
7244
0
        CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7245
0
    psParseInfo->sFieldList.ids = static_cast<int *>(
7246
0
        CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7247
7248
0
    bool bIsFID64 = false;
7249
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7250
0
    {
7251
0
        swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7252
0
        GDALDataset *poTableDS = this;
7253
7254
0
        if (psTableDef->data_source != nullptr)
7255
0
        {
7256
0
            poTableDS = GDALDataset::FromHandle(
7257
0
                OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7258
0
            CPLAssert(poTableDS != nullptr);
7259
0
            poTableDS->Dereference();
7260
0
        }
7261
7262
0
        OGRLayer *poSrcLayer =
7263
0
            poTableDS->GetLayerByName(psTableDef->table_name);
7264
7265
0
        for (int iField = 0;
7266
0
             iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7267
0
        {
7268
0
            OGRFieldDefn *poFDefn =
7269
0
                poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7270
0
            const int iOutField = psParseInfo->sFieldList.count++;
7271
0
            psParseInfo->sFieldList.names[iOutField] =
7272
0
                const_cast<char *>(poFDefn->GetNameRef());
7273
0
            if (poFDefn->GetType() == OFTInteger)
7274
0
            {
7275
0
                if (poFDefn->GetSubType() == OFSTBoolean)
7276
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7277
0
                else
7278
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7279
0
            }
7280
0
            else if (poFDefn->GetType() == OFTInteger64)
7281
0
            {
7282
0
                if (poFDefn->GetSubType() == OFSTBoolean)
7283
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7284
0
                else
7285
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7286
0
            }
7287
0
            else if (poFDefn->GetType() == OFTReal)
7288
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7289
0
            else if (poFDefn->GetType() == OFTString)
7290
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7291
0
            else if (poFDefn->GetType() == OFTTime)
7292
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7293
0
            else if (poFDefn->GetType() == OFTDate)
7294
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7295
0
            else if (poFDefn->GetType() == OFTDateTime)
7296
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7297
0
            else
7298
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7299
7300
0
            psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7301
0
            psParseInfo->sFieldList.ids[iOutField] = iField;
7302
0
        }
7303
7304
0
        if (iTable == 0)
7305
0
        {
7306
0
            nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7307
0
        }
7308
7309
0
        if (iTable == 0 ||
7310
0
            (poSelectParseOptions &&
7311
0
             poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7312
0
        {
7313
7314
0
            for (int iField = 0;
7315
0
                 iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7316
0
                 iField++)
7317
0
            {
7318
0
                OGRGeomFieldDefn *poFDefn =
7319
0
                    poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7320
0
                const int iOutField = psParseInfo->sFieldList.count++;
7321
0
                psParseInfo->sFieldList.names[iOutField] =
7322
0
                    const_cast<char *>(poFDefn->GetNameRef());
7323
0
                if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7324
0
                    psParseInfo->sFieldList.names[iOutField] =
7325
0
                        const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7326
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7327
7328
0
                psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7329
0
                psParseInfo->sFieldList.ids[iOutField] =
7330
0
                    GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7331
0
                        poSrcLayer->GetLayerDefn(), iField);
7332
0
            }
7333
0
        }
7334
7335
0
        if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7336
0
            EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7337
0
        {
7338
0
            bIsFID64 = true;
7339
0
        }
7340
0
    }
7341
7342
    /* -------------------------------------------------------------------- */
7343
    /*      Expand '*' in 'SELECT *' now before we add the pseudo fields    */
7344
    /* -------------------------------------------------------------------- */
7345
0
    const bool bAlwaysPrefixWithTableName =
7346
0
        poSelectParseOptions &&
7347
0
        poSelectParseOptions->bAlwaysPrefixWithTableName;
7348
0
    if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7349
0
                                      bAlwaysPrefixWithTableName) != CE_None)
7350
0
    {
7351
0
        DestroyParseInfo(psParseInfo);
7352
0
        return nullptr;
7353
0
    }
7354
7355
0
    for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7356
0
    {
7357
0
        psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7358
0
            const_cast<char *>(SpecialFieldNames[iField]);
7359
0
        psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7360
0
            (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7361
0
                                            : SpecialFieldTypes[iField];
7362
0
        psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7363
0
        psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7364
0
            nFirstLayerFirstSpecialFieldIndex + iField;
7365
0
        psParseInfo->sFieldList.count++;
7366
0
    }
7367
7368
    /* In the case a layer has an explicit FID column name, then add it */
7369
    /* so it can be selected */
7370
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7371
0
    {
7372
0
        swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7373
0
        GDALDataset *poTableDS = this;
7374
7375
0
        if (psTableDef->data_source != nullptr)
7376
0
        {
7377
0
            poTableDS = GDALDataset::FromHandle(
7378
0
                OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7379
0
            CPLAssert(poTableDS != nullptr);
7380
0
            poTableDS->Dereference();
7381
0
        }
7382
7383
0
        OGRLayer *poSrcLayer =
7384
0
            poTableDS->GetLayerByName(psTableDef->table_name);
7385
7386
0
        const char *pszFID = poSrcLayer->GetFIDColumn();
7387
0
        if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7388
0
            poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7389
0
        {
7390
0
            const int iOutField = psParseInfo->sFieldList.count++;
7391
0
            psParseInfo->sFieldList.names[iOutField] =
7392
0
                const_cast<char *>(pszFID);
7393
0
            if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7394
0
                EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7395
0
            {
7396
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7397
0
            }
7398
0
            else
7399
0
            {
7400
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7401
0
            }
7402
0
            psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7403
0
            psParseInfo->sFieldList.ids[iOutField] =
7404
0
                poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7405
0
        }
7406
0
    }
7407
7408
    /* -------------------------------------------------------------------- */
7409
    /*      Finish the parse operation.                                     */
7410
    /* -------------------------------------------------------------------- */
7411
0
    if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7412
0
        CE_None)
7413
0
    {
7414
0
        DestroyParseInfo(psParseInfo);
7415
0
        return nullptr;
7416
0
    }
7417
7418
    /* -------------------------------------------------------------------- */
7419
    /*      Extract the WHERE expression to use separately.                 */
7420
    /* -------------------------------------------------------------------- */
7421
0
    if (psSelectInfo->where_expr != nullptr)
7422
0
    {
7423
0
        psParseInfo->pszWHERE =
7424
0
            psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7425
        // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7426
0
    }
7427
7428
0
    return psParseInfo;
7429
0
}
7430
7431
//! @endcond
7432
7433
/************************************************************************/
7434
/*                          ReleaseResultSet()                          */
7435
/************************************************************************/
7436
7437
/**
7438
 \brief Release results of ExecuteSQL().
7439
7440
 This method should only be used to deallocate OGRLayers resulting from
7441
 an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
7442
 results set before destroying the GDALDataset may cause errors.
7443
7444
 This method is the same as the C function GDALDatasetReleaseResultSet() and the
7445
 deprecated OGR_DS_ReleaseResultSet().
7446
7447
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7448
7449
 @param poResultsSet the result of a previous ExecuteSQL() call.
7450
*/
7451
7452
void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7453
7454
0
{
7455
0
    delete poResultsSet;
7456
0
}
7457
7458
/************************************************************************/
7459
/*                            GetStyleTable()                           */
7460
/************************************************************************/
7461
7462
/**
7463
 \brief Returns dataset style table.
7464
7465
 This method is the same as the C function GDALDatasetGetStyleTable() and the
7466
 deprecated OGR_DS_GetStyleTable().
7467
7468
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7469
7470
 @return pointer to a style table which should not be modified or freed by the
7471
 caller.
7472
*/
7473
7474
OGRStyleTable *GDALDataset::GetStyleTable()
7475
0
{
7476
0
    return m_poStyleTable;
7477
0
}
7478
7479
/************************************************************************/
7480
/*                         SetStyleTableDirectly()                      */
7481
/************************************************************************/
7482
7483
/**
7484
 \brief Set dataset style table.
7485
7486
 This method operate exactly as SetStyleTable() except that it
7487
 assumes ownership of the passed table.
7488
7489
 This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7490
 and the deprecated OGR_DS_SetStyleTableDirectly().
7491
7492
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7493
7494
 @param poStyleTable pointer to style table to set
7495
7496
*/
7497
void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7498
0
{
7499
0
    if (m_poStyleTable)
7500
0
        delete m_poStyleTable;
7501
0
    m_poStyleTable = poStyleTable;
7502
0
}
7503
7504
/************************************************************************/
7505
/*                            SetStyleTable()                           */
7506
/************************************************************************/
7507
7508
/**
7509
 \brief Set dataset style table.
7510
7511
 This method operate exactly as SetStyleTableDirectly() except
7512
 that it does not assume ownership of the passed table.
7513
7514
 This method is the same as the C function GDALDatasetSetStyleTable() and the
7515
 deprecated OGR_DS_SetStyleTable().
7516
7517
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7518
7519
 @param poStyleTable pointer to style table to set
7520
7521
*/
7522
7523
void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7524
0
{
7525
0
    if (m_poStyleTable)
7526
0
        delete m_poStyleTable;
7527
0
    if (poStyleTable)
7528
0
        m_poStyleTable = poStyleTable->Clone();
7529
0
}
7530
7531
/************************************************************************/
7532
/*                         IsGenericSQLDialect()                        */
7533
/************************************************************************/
7534
7535
//! @cond Doxygen_Suppress
7536
int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7537
0
{
7538
0
    return pszDialect != nullptr &&
7539
0
           (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7540
0
}
7541
7542
//! @endcond
7543
7544
/************************************************************************/
7545
/*                            GetLayerCount()                           */
7546
/************************************************************************/
7547
7548
/**
7549
 \brief Get the number of layers in this dataset.
7550
7551
 This method is the same as the C function GDALDatasetGetLayerCount(),
7552
 and the deprecated OGR_DS_GetLayerCount().
7553
7554
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7555
7556
 @return layer count.
7557
*/
7558
7559
int GDALDataset::GetLayerCount()
7560
0
{
7561
0
    return 0;
7562
0
}
7563
7564
/************************************************************************/
7565
/*                                GetLayer()                            */
7566
/************************************************************************/
7567
7568
/**
7569
 \fn GDALDataset::GetLayer(int)
7570
 \brief Fetch a layer by index.
7571
7572
 The returned layer remains owned by the
7573
 GDALDataset and should not be deleted by the application.
7574
7575
 See GetLayers() for a C++ iterator version of this method.
7576
7577
 This method is the same as the C function GDALDatasetGetLayer() and the
7578
 deprecated OGR_DS_GetLayer().
7579
7580
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7581
7582
 @param iLayer a layer number between 0 and GetLayerCount()-1.
7583
7584
 @return the layer, or NULL if iLayer is out of range or an error occurs.
7585
7586
 @see GetLayers()
7587
*/
7588
7589
OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)
7590
0
{
7591
0
    return nullptr;
7592
0
}
7593
7594
/************************************************************************/
7595
/*                                IsLayerPrivate()                      */
7596
/************************************************************************/
7597
7598
/**
7599
 \fn GDALDataset::IsLayerPrivate(int)
7600
 \brief Returns true if the layer at the specified index is deemed a private or
7601
 system table, or an internal detail only.
7602
7603
 This method is the same as the C function GDALDatasetIsLayerPrivate().
7604
7605
 @param iLayer a layer number between 0 and GetLayerCount()-1.
7606
7607
 @return true if the layer is a private or system table.
7608
7609
 @since GDAL 3.4
7610
*/
7611
7612
bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7613
0
{
7614
0
    return false;
7615
0
}
7616
7617
/************************************************************************/
7618
/*                           ResetReading()                             */
7619
/************************************************************************/
7620
7621
/**
7622
 \brief Reset feature reading to start on the first feature.
7623
7624
 This affects GetNextFeature().
7625
7626
 Depending on drivers, this may also have the side effect of calling
7627
 OGRLayer::ResetReading() on the layers of this dataset.
7628
7629
 This method is the same as the C function GDALDatasetResetReading().
7630
7631
 @since GDAL 2.2
7632
*/
7633
void GDALDataset::ResetReading()
7634
0
{
7635
0
    if (!m_poPrivate)
7636
0
        return;
7637
0
    m_poPrivate->nCurrentLayerIdx = 0;
7638
0
    m_poPrivate->nLayerCount = -1;
7639
0
    m_poPrivate->poCurrentLayer = nullptr;
7640
0
    m_poPrivate->nFeatureReadInLayer = 0;
7641
0
    m_poPrivate->nFeatureReadInDataset = 0;
7642
0
    m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7643
0
    m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7644
0
}
7645
7646
/************************************************************************/
7647
/*                         GDALDatasetResetReading()                    */
7648
/************************************************************************/
7649
7650
/**
7651
 \brief Reset feature reading to start on the first feature.
7652
7653
 This affects GDALDatasetGetNextFeature().
7654
7655
 Depending on drivers, this may also have the side effect of calling
7656
 OGR_L_ResetReading() on the layers of this dataset.
7657
7658
 This method is the same as the C++ method GDALDataset::ResetReading()
7659
7660
 @param hDS dataset handle
7661
 @since GDAL 2.2
7662
*/
7663
void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7664
0
{
7665
0
    VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7666
7667
0
    return GDALDataset::FromHandle(hDS)->ResetReading();
7668
0
}
7669
7670
/************************************************************************/
7671
/*                          GetNextFeature()                            */
7672
/************************************************************************/
7673
7674
/**
7675
 \brief Fetch the next available feature from this dataset.
7676
7677
 This method is intended for the few drivers where OGRLayer::GetNextFeature()
7678
 is not efficient, but in general OGRLayer::GetNextFeature() is a more
7679
 natural API.
7680
7681
 See GetFeatures() for a C++ iterator version of this method.
7682
7683
 The returned feature becomes the responsibility of the caller to
7684
 delete with OGRFeature::DestroyFeature().
7685
7686
 Depending on the driver, this method may return features from layers in a
7687
 non sequential way. This is what may happen when the
7688
 ODsCRandomLayerRead capability is declared (for example for the
7689
 OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7690
 advised to use GDALDataset::GetNextFeature() instead of
7691
 OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7692
 implementation.
7693
7694
 The default implementation, used by most drivers, will
7695
 however iterate over each layer, and then over each feature within this
7696
 layer.
7697
7698
 This method takes into account spatial and attribute filters set on layers that
7699
 will be iterated upon.
7700
7701
 The ResetReading() method can be used to start at the beginning again.
7702
7703
 Depending on drivers, this may also have the side effect of calling
7704
 OGRLayer::GetNextFeature() on the layers of this dataset.
7705
7706
 This method is the same as the C function GDALDatasetGetNextFeature().
7707
7708
 @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
7709
                          layer to which the object belongs to, or NULL.
7710
                          It is possible that the output of *ppoBelongingLayer
7711
                          to be NULL despite the feature not being NULL.
7712
 @param pdfProgressPct    a pointer to a double variable to receive the
7713
                          percentage progress (in [0,1] range), or NULL.
7714
                          On return, the pointed value might be negative if
7715
                          determining the progress is not possible.
7716
 @param pfnProgress       a progress callback to report progress (for
7717
                          GetNextFeature() calls that might have a long
7718
                          duration) and offer cancellation possibility, or NULL.
7719
 @param pProgressData     user data provided to pfnProgress, or NULL
7720
 @return a feature, or NULL if no more features are available.
7721
 @since GDAL 2.2
7722
 @see GetFeatures()
7723
*/
7724
7725
OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
7726
                                        double *pdfProgressPct,
7727
                                        GDALProgressFunc pfnProgress,
7728
                                        void *pProgressData)
7729
0
{
7730
0
    if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
7731
0
    {
7732
0
        if (ppoBelongingLayer != nullptr)
7733
0
            *ppoBelongingLayer = nullptr;
7734
0
        if (pdfProgressPct != nullptr)
7735
0
            *pdfProgressPct = 1.0;
7736
0
        if (pfnProgress != nullptr)
7737
0
            pfnProgress(1.0, "", pProgressData);
7738
0
        return nullptr;
7739
0
    }
7740
7741
0
    if (m_poPrivate->poCurrentLayer == nullptr &&
7742
0
        (pdfProgressPct != nullptr || pfnProgress != nullptr))
7743
0
    {
7744
0
        if (m_poPrivate->nLayerCount < 0)
7745
0
        {
7746
0
            m_poPrivate->nLayerCount = GetLayerCount();
7747
0
        }
7748
7749
0
        if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
7750
0
        {
7751
0
            m_poPrivate->nTotalFeatures = 0;
7752
0
            for (int i = 0; i < m_poPrivate->nLayerCount; i++)
7753
0
            {
7754
0
                OGRLayer *poLayer = GetLayer(i);
7755
0
                if (poLayer == nullptr ||
7756
0
                    !poLayer->TestCapability(OLCFastFeatureCount))
7757
0
                {
7758
0
                    m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7759
0
                    break;
7760
0
                }
7761
0
                GIntBig nCount = poLayer->GetFeatureCount(FALSE);
7762
0
                if (nCount < 0)
7763
0
                {
7764
0
                    m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7765
0
                    break;
7766
0
                }
7767
0
                m_poPrivate->nTotalFeatures += nCount;
7768
0
            }
7769
0
        }
7770
0
    }
7771
7772
0
    while (true)
7773
0
    {
7774
0
        if (m_poPrivate->poCurrentLayer == nullptr)
7775
0
        {
7776
0
            m_poPrivate->poCurrentLayer =
7777
0
                GetLayer(m_poPrivate->nCurrentLayerIdx);
7778
0
            if (m_poPrivate->poCurrentLayer == nullptr)
7779
0
            {
7780
0
                m_poPrivate->nCurrentLayerIdx = -1;
7781
0
                if (ppoBelongingLayer != nullptr)
7782
0
                    *ppoBelongingLayer = nullptr;
7783
0
                if (pdfProgressPct != nullptr)
7784
0
                    *pdfProgressPct = 1.0;
7785
0
                return nullptr;
7786
0
            }
7787
0
            m_poPrivate->poCurrentLayer->ResetReading();
7788
0
            m_poPrivate->nFeatureReadInLayer = 0;
7789
0
            if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
7790
0
            {
7791
0
                if (m_poPrivate->poCurrentLayer->TestCapability(
7792
0
                        OLCFastFeatureCount))
7793
0
                    m_poPrivate->nTotalFeaturesInLayer =
7794
0
                        m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7795
0
                else
7796
0
                    m_poPrivate->nTotalFeaturesInLayer = 0;
7797
0
            }
7798
0
        }
7799
0
        OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7800
0
        if (poFeature == nullptr)
7801
0
        {
7802
0
            m_poPrivate->nCurrentLayerIdx++;
7803
0
            m_poPrivate->poCurrentLayer = nullptr;
7804
0
            continue;
7805
0
        }
7806
7807
0
        m_poPrivate->nFeatureReadInLayer++;
7808
0
        m_poPrivate->nFeatureReadInDataset++;
7809
0
        if (pdfProgressPct != nullptr || pfnProgress != nullptr)
7810
0
        {
7811
0
            double dfPct = 0.0;
7812
0
            if (m_poPrivate->nTotalFeatures > 0)
7813
0
            {
7814
0
                dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7815
0
                        m_poPrivate->nTotalFeatures;
7816
0
            }
7817
0
            else
7818
0
            {
7819
0
                dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
7820
0
                        m_poPrivate->nLayerCount;
7821
0
                if (m_poPrivate->nTotalFeaturesInLayer > 0)
7822
0
                {
7823
0
                    dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7824
0
                             m_poPrivate->nTotalFeaturesInLayer /
7825
0
                             m_poPrivate->nLayerCount;
7826
0
                }
7827
0
            }
7828
0
            if (pdfProgressPct)
7829
0
                *pdfProgressPct = dfPct;
7830
0
            if (pfnProgress)
7831
0
                pfnProgress(dfPct, "", nullptr);
7832
0
        }
7833
7834
0
        if (ppoBelongingLayer != nullptr)
7835
0
            *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7836
0
        return poFeature;
7837
0
    }
7838
0
}
7839
7840
/************************************************************************/
7841
/*                     GDALDatasetGetNextFeature()                      */
7842
/************************************************************************/
7843
/**
7844
 \brief Fetch the next available feature from this dataset.
7845
7846
 This method is intended for the few drivers where OGR_L_GetNextFeature()
7847
 is not efficient, but in general OGR_L_GetNextFeature() is a more
7848
 natural API.
7849
7850
 The returned feature becomes the responsibility of the caller to
7851
 delete with OGRFeature::DestroyFeature().
7852
7853
 Depending on the driver, this method may return features from layers in a
7854
 non sequential way. This is what may happen when the
7855
 ODsCRandomLayerRead capability is declared (for example for the
7856
 OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7857
 advised to use GDALDataset::GetNextFeature() instead of
7858
 OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7859
 implementation.
7860
7861
 The default implementation, used by most drivers, will
7862
 however iterate over each layer, and then over each feature within this
7863
 layer.
7864
7865
 This method takes into account spatial and attribute filters set on layers that
7866
 will be iterated upon.
7867
7868
 The ResetReading() method can be used to start at the beginning again.
7869
7870
 Depending on drivers, this may also have the side effect of calling
7871
 OGRLayer::GetNextFeature() on the layers of this dataset.
7872
7873
 This method is the same as the C++ method GDALDataset::GetNextFeature()
7874
7875
 @param hDS               dataset handle.
7876
 @param phBelongingLayer  a pointer to a OGRLayer* variable to receive the
7877
                          layer to which the object belongs to, or NULL.
7878
                          It is possible that the output of *ppoBelongingLayer
7879
                          to be NULL despite the feature not being NULL.
7880
 @param pdfProgressPct    a pointer to a double variable to receive the
7881
                          percentage progress (in [0,1] range), or NULL.
7882
                          On return, the pointed value might be negative if
7883
                          determining the progress is not possible.
7884
 @param pfnProgress       a progress callback to report progress (for
7885
                          GetNextFeature() calls that might have a long
7886
                          duration) and offer cancellation possibility, or NULL
7887
 @param pProgressData     user data provided to pfnProgress, or NULL
7888
 @return a feature, or NULL if no more features are available.
7889
 @since GDAL 2.2
7890
*/
7891
OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
7892
                                              OGRLayerH *phBelongingLayer,
7893
                                              double *pdfProgressPct,
7894
                                              GDALProgressFunc pfnProgress,
7895
                                              void *pProgressData)
7896
0
{
7897
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
7898
7899
0
    return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
7900
0
        reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
7901
0
        pfnProgress, pProgressData));
7902
0
}
7903
7904
/************************************************************************/
7905
/*                            TestCapability()                          */
7906
/************************************************************************/
7907
7908
/**
7909
 \fn GDALDataset::TestCapability( const char * pszCap )
7910
 \brief Test if capability is available.
7911
7912
 One of the following dataset capability names can be passed into this
7913
 method, and a TRUE or FALSE value will be returned indicating whether or not
7914
 the capability is available for this object.
7915
7916
 <ul>
7917
  <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7918
  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7919
          layers.<p>
7920
  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7921
          datasource support CreateGeomField() just after layer creation.<p>
7922
  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7923
          geometries.<p>
7924
  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7925
          transactions.<p>
7926
  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7927
          transactions through emulation.<p>
7928
  <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7929
          GetNextFeature() implementation, potentially returning features from
7930
          layers in a non sequential way.<p>
7931
  <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7932
         CreateFeature() on layers in a non sequential way.<p>
7933
 </ul>
7934
7935
 The \#define macro forms of the capability names should be used in preference
7936
 to the strings themselves to avoid misspelling.
7937
7938
 This method is the same as the C function GDALDatasetTestCapability() and the
7939
 deprecated OGR_DS_TestCapability().
7940
7941
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7942
7943
 @param pszCap the capability to test.
7944
7945
 @return TRUE if capability available otherwise FALSE.
7946
*/
7947
7948
int GDALDataset::TestCapability(CPL_UNUSED const char *pszCap)
7949
0
{
7950
0
    return FALSE;
7951
0
}
7952
7953
/************************************************************************/
7954
/*                     GDALDatasetTestCapability()                      */
7955
/************************************************************************/
7956
7957
/**
7958
 \brief Test if capability is available.
7959
7960
 One of the following dataset capability names can be passed into this
7961
 function, and a TRUE or FALSE value will be returned indicating whether or not
7962
 the capability is available for this object.
7963
7964
 <ul>
7965
  <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7966
  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7967
          layers.<p>
7968
  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7969
          datasource support CreateGeomField() just after layer creation.<p>
7970
  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7971
          geometries.<p>
7972
  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7973
          transactions.<p>
7974
  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7975
          transactions through emulation.<p>
7976
  <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7977
          GetNextFeature() implementation, potentially returning features from
7978
          layers in a non sequential way.<p>
7979
  <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7980
          CreateFeature() on layers in a non sequential way.<p>
7981
 </ul>
7982
7983
 The \#define macro forms of the capability names should be used in preference
7984
 to the strings themselves to avoid misspelling.
7985
7986
 This function is the same as the C++ method GDALDataset::TestCapability()
7987
7988
 @since GDAL 2.0
7989
7990
 @param hDS the dataset handle.
7991
 @param pszCap the capability to test.
7992
7993
 @return TRUE if capability available otherwise FALSE.
7994
*/
7995
int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
7996
7997
0
{
7998
0
    VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
7999
0
    VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
8000
8001
0
    return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
8002
0
}
8003
8004
/************************************************************************/
8005
/*                           StartTransaction()                         */
8006
/************************************************************************/
8007
8008
/**
8009
 \fn GDALDataset::StartTransaction(int)
8010
 \brief For datasources which support transactions, StartTransaction creates a
8011
`transaction.
8012
8013
 If starting the transaction fails, will return
8014
 OGRERR_FAILURE. Datasources which do not support transactions will
8015
 always return OGRERR_UNSUPPORTED_OPERATION.
8016
8017
 Nested transactions are not supported.
8018
8019
 All changes done after the start of the transaction are definitely applied in
8020
 the datasource if CommitTransaction() is called. They may be canceled by
8021
 calling RollbackTransaction() instead.
8022
8023
 At the time of writing, transactions only apply on vector layers.
8024
8025
 Datasets that support transactions will advertise the ODsCTransactions
8026
 capability.  Use of transactions at dataset level is generally preferred to
8027
 transactions at layer level, whose scope is rarely limited to the layer from
8028
 which it was started.
8029
8030
 In case StartTransaction() fails, neither CommitTransaction() or
8031
 RollbackTransaction() should be called.
8032
8033
 If an error occurs after a successful StartTransaction(), the whole transaction
8034
 may or may not be implicitly canceled, depending on drivers. (e.g.  the PG
8035
 driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
8036
 an explicit call to RollbackTransaction() should be done to keep things
8037
 balanced.
8038
8039
 By default, when bForce is set to FALSE, only "efficient" transactions will be
8040
 attempted. Some drivers may offer an emulation of transactions, but sometimes
8041
 with significant overhead, in which case the user must explicitly allow for
8042
 such an emulation by setting bForce to TRUE. Drivers that offer emulated
8043
 transactions should advertise the ODsCEmulatedTransactions capability (and not
8044
 ODsCTransactions).
8045
8046
 This function is the same as the C function GDALDatasetStartTransaction().
8047
8048
 @param bForce can be set to TRUE if an emulation, possibly slow, of a
8049
 transaction
8050
               mechanism is acceptable.
8051
8052
 @return OGRERR_NONE on success.
8053
 @since GDAL 2.0
8054
*/
8055
8056
OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
8057
0
{
8058
0
    return OGRERR_UNSUPPORTED_OPERATION;
8059
0
}
8060
8061
/************************************************************************/
8062
/*                      GDALDatasetStartTransaction()                   */
8063
/************************************************************************/
8064
8065
/**
8066
 \brief For datasources which support transactions, StartTransaction creates a
8067
 transaction.
8068
8069
 If starting the transaction fails, will return
8070
 OGRERR_FAILURE. Datasources which do not support transactions will
8071
 always return OGRERR_UNSUPPORTED_OPERATION.
8072
8073
 Nested transactions are not supported.
8074
8075
 All changes done after the start of the transaction are definitely applied in
8076
 the datasource if CommitTransaction() is called. They may be canceled by
8077
 calling RollbackTransaction() instead.
8078
8079
 At the time of writing, transactions only apply on vector layers.
8080
8081
 Datasets that support transactions will advertise the ODsCTransactions
8082
 capability.
8083
 Use of transactions at dataset level is generally preferred to transactions at
8084
 layer level, whose scope is rarely limited to the layer from which it was
8085
 started.
8086
8087
 In case StartTransaction() fails, neither CommitTransaction() or
8088
 RollbackTransaction() should be called.
8089
8090
 If an error occurs after a successful StartTransaction(), the whole
8091
 transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8092
 the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8093
 error, an explicit call to RollbackTransaction() should be done to keep things
8094
 balanced.
8095
8096
 By default, when bForce is set to FALSE, only "efficient" transactions will be
8097
 attempted. Some drivers may offer an emulation of transactions, but sometimes
8098
 with significant overhead, in which case the user must explicitly allow for
8099
 such an emulation by setting bForce to TRUE. Drivers that offer emulated
8100
 transactions should advertise the ODsCEmulatedTransactions capability (and not
8101
 ODsCTransactions).
8102
8103
 This function is the same as the C++ method GDALDataset::StartTransaction()
8104
8105
 @param hDS the dataset handle.
8106
 @param bForce can be set to TRUE if an emulation, possibly slow, of a
8107
 transaction
8108
               mechanism is acceptable.
8109
8110
 @return OGRERR_NONE on success.
8111
 @since GDAL 2.0
8112
*/
8113
OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8114
0
{
8115
0
    VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8116
0
                      OGRERR_INVALID_HANDLE);
8117
8118
0
#ifdef OGRAPISPY_ENABLED
8119
0
    if (bOGRAPISpyEnabled)
8120
0
        OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8121
0
#endif
8122
8123
0
    return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8124
0
}
8125
8126
/************************************************************************/
8127
/*                           CommitTransaction()                        */
8128
/************************************************************************/
8129
8130
/**
8131
 \brief For datasources which support transactions, CommitTransaction commits a
8132
 transaction.
8133
8134
 If no transaction is active, or the commit fails, will return
8135
 OGRERR_FAILURE. Datasources which do not support transactions will
8136
 always return OGRERR_UNSUPPORTED_OPERATION.
8137
8138
 Depending on drivers, this may or may not abort layer sequential readings that
8139
 are active.
8140
8141
 This function is the same as the C function GDALDatasetCommitTransaction().
8142
8143
 @return OGRERR_NONE on success.
8144
 @since GDAL 2.0
8145
*/
8146
OGRErr GDALDataset::CommitTransaction()
8147
0
{
8148
0
    return OGRERR_UNSUPPORTED_OPERATION;
8149
0
}
8150
8151
/************************************************************************/
8152
/*                        GDALDatasetCommitTransaction()                */
8153
/************************************************************************/
8154
8155
/**
8156
 \brief For datasources which support transactions, CommitTransaction commits a
8157
 transaction.
8158
8159
 If no transaction is active, or the commit fails, will return
8160
 OGRERR_FAILURE. Datasources which do not support transactions will
8161
 always return OGRERR_UNSUPPORTED_OPERATION.
8162
8163
 Depending on drivers, this may or may not abort layer sequential readings that
8164
 are active.
8165
8166
 This function is the same as the C++ method GDALDataset::CommitTransaction()
8167
8168
 @return OGRERR_NONE on success.
8169
 @since GDAL 2.0
8170
*/
8171
OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8172
0
{
8173
0
    VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8174
0
                      OGRERR_INVALID_HANDLE);
8175
8176
0
#ifdef OGRAPISPY_ENABLED
8177
0
    if (bOGRAPISpyEnabled)
8178
0
        OGRAPISpy_Dataset_CommitTransaction(hDS);
8179
0
#endif
8180
8181
0
    return GDALDataset::FromHandle(hDS)->CommitTransaction();
8182
0
}
8183
8184
/************************************************************************/
8185
/*                           RollbackTransaction()                      */
8186
/************************************************************************/
8187
8188
/**
8189
 \brief For datasources which support transactions, RollbackTransaction will
8190
 roll back a datasource to its state before the start of the current
8191
 transaction.
8192
 If no transaction is active, or the rollback fails, will return
8193
 OGRERR_FAILURE. Datasources which do not support transactions will
8194
 always return OGRERR_UNSUPPORTED_OPERATION.
8195
8196
 This function is the same as the C function GDALDatasetRollbackTransaction().
8197
8198
 @return OGRERR_NONE on success.
8199
 @since GDAL 2.0
8200
*/
8201
OGRErr GDALDataset::RollbackTransaction()
8202
0
{
8203
0
    return OGRERR_UNSUPPORTED_OPERATION;
8204
0
}
8205
8206
/************************************************************************/
8207
/*                     GDALDatasetRollbackTransaction()                 */
8208
/************************************************************************/
8209
8210
/**
8211
 \brief For datasources which support transactions, RollbackTransaction will
8212
 roll back a datasource to its state before the start of the current
8213
 transaction.
8214
 If no transaction is active, or the rollback fails, will return
8215
 OGRERR_FAILURE. Datasources which do not support transactions will
8216
 always return OGRERR_UNSUPPORTED_OPERATION.
8217
8218
 This function is the same as the C++ method GDALDataset::RollbackTransaction().
8219
8220
 @return OGRERR_NONE on success.
8221
 @since GDAL 2.0
8222
*/
8223
OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8224
0
{
8225
0
    VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8226
0
                      OGRERR_INVALID_HANDLE);
8227
8228
0
#ifdef OGRAPISPY_ENABLED
8229
0
    if (bOGRAPISpyEnabled)
8230
0
        OGRAPISpy_Dataset_RollbackTransaction(hDS);
8231
0
#endif
8232
8233
0
    return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8234
0
}
8235
8236
//! @cond Doxygen_Suppress
8237
8238
/************************************************************************/
8239
/*                   ShareLockWithParentDataset()                       */
8240
/************************************************************************/
8241
8242
/* To be used typically by the GTiff driver to link overview datasets */
8243
/* with their main dataset, so that they share the same lock */
8244
/* Cf https://github.com/OSGeo/gdal/issues/1488 */
8245
/* The parent dataset should remain alive while the this dataset is alive */
8246
8247
void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8248
0
{
8249
0
    if (m_poPrivate != nullptr)
8250
0
    {
8251
0
        m_poPrivate->poParentDataset = poParentDataset;
8252
0
    }
8253
0
}
8254
8255
/************************************************************************/
8256
/*                   SetQueryLoggerFunc()                               */
8257
/************************************************************************/
8258
8259
bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8260
                                     CPL_UNUSED void *context)
8261
0
{
8262
0
    return false;
8263
0
}
8264
8265
/************************************************************************/
8266
/*                          EnterReadWrite()                            */
8267
/************************************************************************/
8268
8269
int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8270
0
{
8271
0
    if (m_poPrivate == nullptr ||
8272
0
        IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
8273
0
        return FALSE;
8274
8275
0
    if (m_poPrivate->poParentDataset)
8276
0
        return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8277
8278
0
    if (eAccess == GA_Update)
8279
0
    {
8280
0
        if (m_poPrivate->eStateReadWriteMutex ==
8281
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8282
0
        {
8283
            // In case dead-lock would occur, which is not impossible,
8284
            // this can be used to prevent it, but at the risk of other
8285
            // issues.
8286
0
            if (CPLTestBool(
8287
0
                    CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8288
0
            {
8289
0
                m_poPrivate->eStateReadWriteMutex =
8290
0
                    GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8291
0
            }
8292
0
            else
8293
0
            {
8294
0
                m_poPrivate->eStateReadWriteMutex =
8295
0
                    GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8296
0
            }
8297
0
        }
8298
0
        if (m_poPrivate->eStateReadWriteMutex ==
8299
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8300
0
        {
8301
            // There should be no race related to creating this mutex since
8302
            // it should be first created through IWriteBlock() / IRasterIO()
8303
            // and then GDALRasterBlock might call it from another thread.
8304
#ifdef DEBUG_VERBOSE
8305
            CPLDebug("GDAL",
8306
                     "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8307
                     CPLGetPID(), GetDescription());
8308
#endif
8309
0
            CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8310
8311
0
            const int nCountMutex =
8312
0
                m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8313
0
            if (nCountMutex == 0 && eRWFlag == GF_Read)
8314
0
            {
8315
0
                CPLReleaseMutex(m_poPrivate->hMutex);
8316
0
                for (int i = 0; i < nBands; i++)
8317
0
                {
8318
0
                    auto blockCache = papoBands[i]->poBandBlockCache;
8319
0
                    if (blockCache)
8320
0
                        blockCache->WaitCompletionPendingTasks();
8321
0
                }
8322
0
                CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8323
0
            }
8324
8325
0
            return TRUE;
8326
0
        }
8327
0
    }
8328
0
    return FALSE;
8329
0
}
8330
8331
/************************************************************************/
8332
/*                         LeaveReadWrite()                             */
8333
/************************************************************************/
8334
8335
void GDALDataset::LeaveReadWrite()
8336
0
{
8337
0
    if (m_poPrivate)
8338
0
    {
8339
0
        if (m_poPrivate->poParentDataset)
8340
0
        {
8341
0
            m_poPrivate->poParentDataset->LeaveReadWrite();
8342
0
            return;
8343
0
        }
8344
8345
0
        m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8346
0
        CPLReleaseMutex(m_poPrivate->hMutex);
8347
#ifdef DEBUG_VERBOSE
8348
        CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8349
                 CPLGetPID(), GetDescription());
8350
#endif
8351
0
    }
8352
0
}
8353
8354
/************************************************************************/
8355
/*                           InitRWLock()                               */
8356
/************************************************************************/
8357
8358
void GDALDataset::InitRWLock()
8359
0
{
8360
0
    if (m_poPrivate)
8361
0
    {
8362
0
        if (m_poPrivate->poParentDataset)
8363
0
        {
8364
0
            m_poPrivate->poParentDataset->InitRWLock();
8365
0
            return;
8366
0
        }
8367
8368
0
        if (m_poPrivate->eStateReadWriteMutex ==
8369
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8370
0
        {
8371
0
            if (EnterReadWrite(GF_Write))
8372
0
                LeaveReadWrite();
8373
0
        }
8374
0
    }
8375
0
}
8376
8377
/************************************************************************/
8378
/*                       DisableReadWriteMutex()                        */
8379
/************************************************************************/
8380
8381
// The mutex logic is broken in multi-threaded situations, for example
8382
// with 2 WarpedVRT datasets being read at the same time. In that
8383
// particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8384
// to disable it.
8385
void GDALDataset::DisableReadWriteMutex()
8386
0
{
8387
0
    if (m_poPrivate)
8388
0
    {
8389
0
        if (m_poPrivate->poParentDataset)
8390
0
        {
8391
0
            m_poPrivate->poParentDataset->DisableReadWriteMutex();
8392
0
            return;
8393
0
        }
8394
8395
0
        m_poPrivate->eStateReadWriteMutex =
8396
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8397
0
    }
8398
0
}
8399
8400
/************************************************************************/
8401
/*                      TemporarilyDropReadWriteLock()                  */
8402
/************************************************************************/
8403
8404
void GDALDataset::TemporarilyDropReadWriteLock()
8405
0
{
8406
0
    if (m_poPrivate == nullptr)
8407
0
        return;
8408
8409
0
    if (m_poPrivate->poParentDataset)
8410
0
    {
8411
0
        m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8412
0
        return;
8413
0
    }
8414
8415
0
    if (m_poPrivate->hMutex)
8416
0
    {
8417
#ifdef DEBUG_VERBOSE
8418
        CPLDebug("GDAL",
8419
                 "[Thread " CPL_FRMT_GIB "] "
8420
                 "Temporarily drop RW mutex for %s",
8421
                 CPLGetPID(), GetDescription());
8422
#endif
8423
0
        CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8424
0
        const int nCount =
8425
0
            m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8426
#ifdef DEBUG_EXTRA
8427
        m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8428
#endif
8429
0
#ifndef __COVERITY__
8430
0
        for (int i = 0; i < nCount + 1; i++)
8431
0
        {
8432
            // The mutex is recursive
8433
0
            CPLReleaseMutex(m_poPrivate->hMutex);
8434
0
        }
8435
0
#endif
8436
0
    }
8437
0
}
8438
8439
/************************************************************************/
8440
/*                       ReacquireReadWriteLock()                       */
8441
/************************************************************************/
8442
8443
void GDALDataset::ReacquireReadWriteLock()
8444
0
{
8445
0
    if (m_poPrivate == nullptr)
8446
0
        return;
8447
8448
0
    if (m_poPrivate->poParentDataset)
8449
0
    {
8450
0
        m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8451
0
        return;
8452
0
    }
8453
8454
0
    if (m_poPrivate->hMutex)
8455
0
    {
8456
#ifdef DEBUG_VERBOSE
8457
        CPLDebug("GDAL",
8458
                 "[Thread " CPL_FRMT_GIB "] "
8459
                 "Reacquire temporarily dropped RW mutex for %s",
8460
                 CPLGetPID(), GetDescription());
8461
#endif
8462
0
        CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8463
0
        const int nCount =
8464
0
            m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8465
#ifdef DEBUG_EXTRA
8466
        CPLAssert(nCount ==
8467
                  m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8468
#endif
8469
0
        if (nCount == 0)
8470
0
            CPLReleaseMutex(m_poPrivate->hMutex);
8471
0
#ifndef __COVERITY__
8472
0
        for (int i = 0; i < nCount - 1; i++)
8473
0
        {
8474
            // The mutex is recursive
8475
0
            CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8476
0
        }
8477
0
#endif
8478
0
    }
8479
0
}
8480
8481
/************************************************************************/
8482
/*                           AcquireMutex()                             */
8483
/************************************************************************/
8484
8485
int GDALDataset::AcquireMutex()
8486
0
{
8487
0
    if (m_poPrivate == nullptr)
8488
0
        return 0;
8489
0
    if (m_poPrivate->poParentDataset)
8490
0
    {
8491
0
        return m_poPrivate->poParentDataset->AcquireMutex();
8492
0
    }
8493
8494
0
    return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8495
0
}
8496
8497
/************************************************************************/
8498
/*                          ReleaseMutex()                              */
8499
/************************************************************************/
8500
8501
void GDALDataset::ReleaseMutex()
8502
0
{
8503
0
    if (m_poPrivate)
8504
0
    {
8505
0
        if (m_poPrivate->poParentDataset)
8506
0
        {
8507
0
            m_poPrivate->poParentDataset->ReleaseMutex();
8508
0
            return;
8509
0
        }
8510
8511
0
        CPLReleaseMutex(m_poPrivate->hMutex);
8512
0
    }
8513
0
}
8514
8515
//! @endcond
8516
8517
/************************************************************************/
8518
/*              GDALDataset::Features::Iterator::Private                */
8519
/************************************************************************/
8520
8521
struct GDALDataset::Features::Iterator::Private
8522
{
8523
    GDALDataset::FeatureLayerPair m_oPair{};
8524
    GDALDataset *m_poDS = nullptr;
8525
    bool m_bEOF = true;
8526
};
8527
8528
GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8529
0
    : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8530
0
{
8531
0
    m_poPrivate->m_poDS = poDS;
8532
0
    if (bStart)
8533
0
    {
8534
0
        poDS->ResetReading();
8535
0
        m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8536
0
            &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8537
0
        m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8538
0
    }
8539
0
}
8540
8541
0
GDALDataset::Features::Iterator::~Iterator() = default;
8542
8543
const GDALDataset::FeatureLayerPair &
8544
GDALDataset::Features::Iterator::operator*() const
8545
0
{
8546
0
    return m_poPrivate->m_oPair;
8547
0
}
8548
8549
GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8550
0
{
8551
0
    m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8552
0
        &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8553
0
    m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8554
0
    return *this;
8555
0
}
8556
8557
bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8558
0
{
8559
0
    return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8560
0
}
8561
8562
/************************************************************************/
8563
/*                            GetFeatures()                             */
8564
/************************************************************************/
8565
8566
/** Function that return an iterable object over features in the dataset
8567
 * layer.
8568
 *
8569
 * This is a C++ iterator friendly version of GetNextFeature().
8570
 *
8571
 * Using this iterator for standard range-based loops is safe, but
8572
 * due to implementation limitations, you shouldn't try to access
8573
 * (dereference) more than one iterator step at a time, since the
8574
 * FeatureLayerPair reference which is returned is reused.
8575
 *
8576
 * Typical use is:
8577
 * \code{.cpp}
8578
 * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8579
 * {
8580
 *       std::cout << "Feature of layer " <<
8581
 *               oFeatureLayerPair.layer->GetName() << std::endl;
8582
 *       oFeatureLayerPair.feature->DumpReadable();
8583
 * }
8584
 * \endcode
8585
 *
8586
 * @see GetNextFeature()
8587
 *
8588
 * @since GDAL 2.3
8589
 */
8590
GDALDataset::Features GDALDataset::GetFeatures()
8591
0
{
8592
0
    return Features(this);
8593
0
}
8594
8595
/************************************************************************/
8596
/*                                 begin()                              */
8597
/************************************************************************/
8598
8599
/**
8600
 \brief Return beginning of feature iterator.
8601
8602
 @since GDAL 2.3
8603
*/
8604
8605
const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8606
0
{
8607
0
    return {m_poSelf, true};
8608
0
}
8609
8610
/************************************************************************/
8611
/*                                  end()                               */
8612
/************************************************************************/
8613
8614
/**
8615
 \brief Return end of feature iterator.
8616
8617
 @since GDAL 2.3
8618
*/
8619
8620
const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8621
0
{
8622
0
    return {m_poSelf, false};
8623
0
}
8624
8625
/************************************************************************/
8626
/*               GDALDataset::Layers::Iterator::Private                 */
8627
/************************************************************************/
8628
8629
struct GDALDataset::Layers::Iterator::Private
8630
{
8631
    OGRLayer *m_poLayer = nullptr;
8632
    int m_iCurLayer = 0;
8633
    int m_nLayerCount = 0;
8634
    GDALDataset *m_poDS = nullptr;
8635
};
8636
8637
0
GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8638
0
{
8639
0
}
8640
8641
// False positive of cppcheck 1.72
8642
// cppcheck-suppress uninitMemberVar
8643
GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8644
0
    : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8645
0
{
8646
0
}
8647
8648
GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
8649
0
    : m_poPrivate(std::move(oOther.m_poPrivate))
8650
0
{
8651
0
}
8652
8653
GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8654
0
    : m_poPrivate(new Private())
8655
0
{
8656
0
    m_poPrivate->m_poDS = poDS;
8657
0
    m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
8658
0
    if (bStart)
8659
0
    {
8660
0
        if (m_poPrivate->m_nLayerCount)
8661
0
            m_poPrivate->m_poLayer = poDS->GetLayer(0);
8662
0
    }
8663
0
    else
8664
0
    {
8665
0
        m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
8666
0
    }
8667
0
}
8668
8669
0
GDALDataset::Layers::Iterator::~Iterator() = default;
8670
8671
// False positive of cppcheck 1.72
8672
// cppcheck-suppress operatorEqVarError
8673
GDALDataset::Layers::Iterator &
8674
GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
8675
0
{
8676
0
    *m_poPrivate = *oOther.m_poPrivate;
8677
0
    return *this;
8678
0
}
8679
8680
GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
8681
    GDALDataset::Layers::Iterator &&oOther) noexcept
8682
0
{
8683
0
    m_poPrivate = std::move(oOther.m_poPrivate);
8684
0
    return *this;
8685
0
}
8686
8687
OGRLayer *GDALDataset::Layers::Iterator::operator*() const
8688
0
{
8689
0
    return m_poPrivate->m_poLayer;
8690
0
}
8691
8692
GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
8693
0
{
8694
0
    m_poPrivate->m_iCurLayer++;
8695
0
    if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
8696
0
    {
8697
0
        m_poPrivate->m_poLayer =
8698
0
            m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
8699
0
    }
8700
0
    else
8701
0
    {
8702
0
        m_poPrivate->m_poLayer = nullptr;
8703
0
    }
8704
0
    return *this;
8705
0
}
8706
8707
GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
8708
0
{
8709
0
    GDALDataset::Layers::Iterator temp = *this;
8710
0
    ++(*this);
8711
0
    return temp;
8712
0
}
8713
8714
bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
8715
0
{
8716
0
    return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
8717
0
}
8718
8719
/************************************************************************/
8720
/*                             GetLayers()                              */
8721
/************************************************************************/
8722
8723
/** Function that returns an iterable object over layers in the dataset.
8724
 *
8725
 * This is a C++ iterator friendly version of GetLayer().
8726
 *
8727
 * Typical use is:
8728
 * \code{.cpp}
8729
 * for( auto&& poLayer: poDS->GetLayers() )
8730
 * {
8731
 *       std::cout << "Layer  << poLayer->GetName() << std::endl;
8732
 * }
8733
 * \endcode
8734
 *
8735
 * @see GetLayer()
8736
 *
8737
 * @since GDAL 2.3
8738
 */
8739
GDALDataset::Layers GDALDataset::GetLayers()
8740
0
{
8741
0
    return Layers(this);
8742
0
}
8743
8744
/************************************************************************/
8745
/*                                 begin()                              */
8746
/************************************************************************/
8747
8748
/**
8749
 \brief Return beginning of layer iterator.
8750
8751
 @since GDAL 2.3
8752
*/
8753
8754
GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
8755
0
{
8756
0
    return {m_poSelf, true};
8757
0
}
8758
8759
/************************************************************************/
8760
/*                                  end()                               */
8761
/************************************************************************/
8762
8763
/**
8764
 \brief Return end of layer iterator.
8765
8766
 @since GDAL 2.3
8767
*/
8768
8769
GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
8770
0
{
8771
0
    return {m_poSelf, false};
8772
0
}
8773
8774
/************************************************************************/
8775
/*                                  size()                             */
8776
/************************************************************************/
8777
8778
/**
8779
 \brief Get the number of layers in this dataset.
8780
8781
 @return layer count.
8782
8783
 @since GDAL 2.3
8784
*/
8785
8786
size_t GDALDataset::Layers::size() const
8787
0
{
8788
0
    return static_cast<size_t>(m_poSelf->GetLayerCount());
8789
0
}
8790
8791
/************************************************************************/
8792
/*                                operator[]()                          */
8793
/************************************************************************/
8794
/**
8795
 \brief Fetch a layer by index.
8796
8797
 The returned layer remains owned by the
8798
 GDALDataset and should not be deleted by the application.
8799
8800
 @param iLayer a layer number between 0 and size()-1.
8801
8802
 @return the layer, or nullptr if iLayer is out of range or an error occurs.
8803
8804
 @since GDAL 2.3
8805
*/
8806
8807
OGRLayer *GDALDataset::Layers::operator[](int iLayer)
8808
0
{
8809
0
    return m_poSelf->GetLayer(iLayer);
8810
0
}
8811
8812
/************************************************************************/
8813
/*                                operator[]()                          */
8814
/************************************************************************/
8815
/**
8816
 \brief Fetch a layer by index.
8817
8818
 The returned layer remains owned by the
8819
 GDALDataset and should not be deleted by the application.
8820
8821
 @param iLayer a layer number between 0 and size()-1.
8822
8823
 @return the layer, or nullptr if iLayer is out of range or an error occurs.
8824
8825
 @since GDAL 2.3
8826
*/
8827
8828
OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
8829
0
{
8830
0
    return m_poSelf->GetLayer(static_cast<int>(iLayer));
8831
0
}
8832
8833
/************************************************************************/
8834
/*                                operator[]()                          */
8835
/************************************************************************/
8836
/**
8837
 \brief Fetch a layer by name.
8838
8839
 The returned layer remains owned by the
8840
 GDALDataset and should not be deleted by the application.
8841
8842
 @param pszLayerName layer name
8843
8844
 @return the layer, or nullptr if pszLayerName does not match with a layer
8845
8846
 @since GDAL 2.3
8847
*/
8848
8849
OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
8850
0
{
8851
0
    return m_poSelf->GetLayerByName(pszLayerName);
8852
0
}
8853
8854
/************************************************************************/
8855
/*               GDALDataset::Bands::Iterator::Private                 */
8856
/************************************************************************/
8857
8858
struct GDALDataset::Bands::Iterator::Private
8859
{
8860
    GDALRasterBand *m_poBand = nullptr;
8861
    int m_iCurBand = 0;
8862
    int m_nBandCount = 0;
8863
    GDALDataset *m_poDS = nullptr;
8864
};
8865
8866
GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8867
0
    : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
8868
0
{
8869
0
    m_poPrivate->m_poDS = poDS;
8870
0
    m_poPrivate->m_nBandCount = poDS->GetRasterCount();
8871
0
    if (bStart)
8872
0
    {
8873
0
        if (m_poPrivate->m_nBandCount)
8874
0
            m_poPrivate->m_poBand = poDS->GetRasterBand(1);
8875
0
    }
8876
0
    else
8877
0
    {
8878
0
        m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
8879
0
    }
8880
0
}
8881
8882
0
GDALDataset::Bands::Iterator::~Iterator() = default;
8883
8884
GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
8885
0
{
8886
0
    return m_poPrivate->m_poBand;
8887
0
}
8888
8889
GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
8890
0
{
8891
0
    m_poPrivate->m_iCurBand++;
8892
0
    if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
8893
0
    {
8894
0
        m_poPrivate->m_poBand =
8895
0
            m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
8896
0
    }
8897
0
    else
8898
0
    {
8899
0
        m_poPrivate->m_poBand = nullptr;
8900
0
    }
8901
0
    return *this;
8902
0
}
8903
8904
bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
8905
0
{
8906
0
    return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
8907
0
}
8908
8909
/************************************************************************/
8910
/*                            GetBands()                           */
8911
/************************************************************************/
8912
8913
/** Function that returns an iterable object over GDALRasterBand in the dataset.
8914
 *
8915
 * This is a C++ iterator friendly version of GetRasterBand().
8916
 *
8917
 * Typical use is:
8918
 * \code{.cpp}
8919
 * for( auto&& poBand: poDS->GetBands() )
8920
 * {
8921
 *       std::cout << "Band  << poBand->GetDescription() << std::endl;
8922
 * }
8923
 * \endcode
8924
 *
8925
 * @see GetRasterBand()
8926
 *
8927
 * @since GDAL 2.3
8928
 */
8929
GDALDataset::Bands GDALDataset::GetBands()
8930
0
{
8931
0
    return Bands(this);
8932
0
}
8933
8934
/************************************************************************/
8935
/*                                 begin()                              */
8936
/************************************************************************/
8937
8938
/**
8939
 \brief Return beginning of band iterator.
8940
8941
 @since GDAL 2.3
8942
*/
8943
8944
const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
8945
0
{
8946
0
    return {m_poSelf, true};
8947
0
}
8948
8949
/************************************************************************/
8950
/*                                  end()                               */
8951
/************************************************************************/
8952
8953
/**
8954
 \brief Return end of band iterator.
8955
8956
 @since GDAL 2.3
8957
*/
8958
8959
const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
8960
0
{
8961
0
    return {m_poSelf, false};
8962
0
}
8963
8964
/************************************************************************/
8965
/*                                  size()                             */
8966
/************************************************************************/
8967
8968
/**
8969
 \brief Get the number of raster bands in this dataset.
8970
8971
 @return raster band count.
8972
8973
 @since GDAL 2.3
8974
*/
8975
8976
size_t GDALDataset::Bands::size() const
8977
0
{
8978
0
    return static_cast<size_t>(m_poSelf->GetRasterCount());
8979
0
}
8980
8981
/************************************************************************/
8982
/*                                operator[]()                          */
8983
/************************************************************************/
8984
/**
8985
 \brief Fetch a raster band by index.
8986
8987
 The returned band remains owned by the
8988
 GDALDataset and should not be deleted by the application.
8989
8990
 @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
8991
 consistent with the conventions of C/C++, i.e. starting at 0.
8992
8993
 @param iBand a band index between 0 and size()-1.
8994
8995
 @return the band, or nullptr if iBand is out of range or an error occurs.
8996
8997
 @since GDAL 2.3
8998
*/
8999
9000
GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
9001
0
{
9002
0
    return m_poSelf->GetRasterBand(1 + iBand);
9003
0
}
9004
9005
/************************************************************************/
9006
/*                                operator[]()                          */
9007
/************************************************************************/
9008
9009
/**
9010
 \brief Fetch a raster band by index.
9011
9012
 The returned band remains owned by the
9013
 GDALDataset and should not be deleted by the application.
9014
9015
 @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9016
 consistent with the conventions of C/C++, i.e. starting at 0.
9017
9018
 @param iBand a band index between 0 and size()-1.
9019
9020
 @return the band, or nullptr if iBand is out of range or an error occurs.
9021
9022
 @since GDAL 2.3
9023
*/
9024
9025
GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
9026
0
{
9027
0
    return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9028
0
}
9029
9030
/************************************************************************/
9031
/*                           GetRootGroup()                             */
9032
/************************************************************************/
9033
9034
/**
9035
 \brief Return the root GDALGroup of this dataset.
9036
9037
 Only valid for multidimensional datasets.
9038
9039
 This is the same as the C function GDALDatasetGetRootGroup().
9040
9041
 @since GDAL 3.1
9042
*/
9043
9044
std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
9045
0
{
9046
0
    return nullptr;
9047
0
}
9048
9049
/************************************************************************/
9050
/*                        GetRawBinaryLayout()                          */
9051
/************************************************************************/
9052
9053
//! @cond Doxygen_Suppress
9054
/**
9055
 \brief Return the layout of a dataset that can be considered as a raw binary
9056
 format.
9057
9058
 @param sLayout Structure that will be set if the dataset is a raw binary one.
9059
 @return true if the dataset is a raw binary one.
9060
 @since GDAL 3.1
9061
*/
9062
9063
bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
9064
0
{
9065
0
    CPL_IGNORE_RET_VAL(sLayout);
9066
0
    return false;
9067
0
}
9068
9069
//! @endcond
9070
9071
/************************************************************************/
9072
/*                          ClearStatistics()                           */
9073
/************************************************************************/
9074
9075
/**
9076
 \brief Clear statistics
9077
9078
 Only implemented for now in PAM supported datasets
9079
9080
 This is the same as the C function GDALDatasetClearStatistics().
9081
9082
 @since GDAL 3.2
9083
*/
9084
9085
void GDALDataset::ClearStatistics()
9086
0
{
9087
0
    auto poRootGroup = GetRootGroup();
9088
0
    if (poRootGroup)
9089
0
        poRootGroup->ClearStatistics();
9090
0
}
9091
9092
/************************************************************************/
9093
/*                        GDALDatasetClearStatistics()                  */
9094
/************************************************************************/
9095
9096
/**
9097
 \brief Clear statistics
9098
9099
 This is the same as the C++ method GDALDataset::ClearStatistics().
9100
9101
 @since GDAL 3.2
9102
*/
9103
9104
void GDALDatasetClearStatistics(GDALDatasetH hDS)
9105
0
{
9106
0
    VALIDATE_POINTER0(hDS, __func__);
9107
0
    GDALDataset::FromHandle(hDS)->ClearStatistics();
9108
0
}
9109
9110
/************************************************************************/
9111
/*                        GetFieldDomainNames()                         */
9112
/************************************************************************/
9113
9114
/** Returns a list of the names of all field domains stored in the dataset.
9115
 *
9116
 * @note The default implementation assumes that drivers fully populate
9117
 * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9118
 * then a specialized implementation of GetFieldDomainNames() must be
9119
 * implemented.
9120
 *
9121
 * @param papszOptions Driver specific options determining how attributes
9122
 * should be retrieved. Pass nullptr for default behavior.
9123
 *
9124
 * @return list of field domain names
9125
 * @since GDAL 3.5
9126
 */
9127
std::vector<std::string>
9128
GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9129
0
{
9130
9131
0
    std::vector<std::string> names;
9132
0
    names.reserve(m_oMapFieldDomains.size());
9133
0
    for (const auto &it : m_oMapFieldDomains)
9134
0
    {
9135
0
        names.emplace_back(it.first);
9136
0
    }
9137
0
    return names;
9138
0
}
9139
9140
/************************************************************************/
9141
/*                      GDALDatasetGetFieldDomainNames()                */
9142
/************************************************************************/
9143
9144
/** Returns a list of the names of all field domains stored in the dataset.
9145
 *
9146
 * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9147
 *
9148
 * @param hDS Dataset handle.
9149
 * @param papszOptions Driver specific options determining how attributes
9150
 * should be retrieved. Pass nullptr for default behavior.
9151
 *
9152
 * @return list of field domain names, to be freed with CSLDestroy()
9153
 * @since GDAL 3.5
9154
 */
9155
char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9156
                                      CSLConstList papszOptions)
9157
0
{
9158
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9159
0
    auto names =
9160
0
        GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9161
0
    CPLStringList res;
9162
0
    for (const auto &name : names)
9163
0
    {
9164
0
        res.AddString(name.c_str());
9165
0
    }
9166
0
    return res.StealList();
9167
0
}
9168
9169
/************************************************************************/
9170
/*                        GetFieldDomain()                              */
9171
/************************************************************************/
9172
9173
/** Get a field domain from its name.
9174
 *
9175
 * @return the field domain, or nullptr if not found.
9176
 * @since GDAL 3.3
9177
 */
9178
const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9179
0
{
9180
0
    const auto iter = m_oMapFieldDomains.find(name);
9181
0
    if (iter == m_oMapFieldDomains.end())
9182
0
        return nullptr;
9183
0
    return iter->second.get();
9184
0
}
9185
9186
/************************************************************************/
9187
/*                      GDALDatasetGetFieldDomain()                     */
9188
/************************************************************************/
9189
9190
/** Get a field domain from its name.
9191
 *
9192
 * This is the same as the C++ method GDALDataset::GetFieldDomain().
9193
 *
9194
 * @param hDS Dataset handle.
9195
 * @param pszName Name of field domain.
9196
 * @return the field domain (ownership remains to the dataset), or nullptr if
9197
 * not found.
9198
 * @since GDAL 3.3
9199
 */
9200
OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9201
0
{
9202
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9203
0
    VALIDATE_POINTER1(pszName, __func__, nullptr);
9204
0
    return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9205
0
        GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9206
0
}
9207
9208
/************************************************************************/
9209
/*                         AddFieldDomain()                             */
9210
/************************************************************************/
9211
9212
/** Add a field domain to the dataset.
9213
 *
9214
 * Only a few drivers will support this operation, and some of them might only
9215
 * support it only for some types of field domains.
9216
 * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9217
 * support this operation. A dataset having at least some support for this
9218
 * operation should report the ODsCAddFieldDomain dataset capability.
9219
 *
9220
 * Anticipated failures will not be emitted through the CPLError()
9221
 * infrastructure, but will be reported in the failureReason output parameter.
9222
 *
9223
 * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9224
 * default implementation of GetFieldDomainNames() to work correctly, or
9225
 * alternatively a specialized implementation of GetFieldDomainNames() should be
9226
 * implemented.
9227
 *
9228
 * @param domain The domain definition.
9229
 * @param failureReason      Output parameter. Will contain an error message if
9230
 *                           an error occurs.
9231
 * @return true in case of success.
9232
 * @since GDAL 3.3
9233
 */
9234
bool GDALDataset::AddFieldDomain(
9235
    CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9236
    std::string &failureReason)
9237
0
{
9238
0
    failureReason = "AddFieldDomain not supported by this driver";
9239
0
    return false;
9240
0
}
9241
9242
/************************************************************************/
9243
/*                     GDALDatasetAddFieldDomain()                      */
9244
/************************************************************************/
9245
9246
/** Add a field domain to the dataset.
9247
 *
9248
 * Only a few drivers will support this operation, and some of them might only
9249
 * support it only for some types of field domains.
9250
 * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9251
 * support this operation. A dataset having at least some support for this
9252
 * operation should report the ODsCAddFieldDomain dataset capability.
9253
 *
9254
 * Anticipated failures will not be emitted through the CPLError()
9255
 * infrastructure, but will be reported in the ppszFailureReason output
9256
 * parameter.
9257
 *
9258
 * @param hDS                Dataset handle.
9259
 * @param hFieldDomain       The domain definition. Contrary to the C++ version,
9260
 *                           the passed object is copied.
9261
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9262
 *                           an error occurs (*ppszFailureReason to be freed
9263
 *                           with CPLFree). May be NULL.
9264
 * @return true in case of success.
9265
 * @since GDAL 3.3
9266
 */
9267
bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9268
                               char **ppszFailureReason)
9269
0
{
9270
0
    VALIDATE_POINTER1(hDS, __func__, false);
9271
0
    VALIDATE_POINTER1(hFieldDomain, __func__, false);
9272
0
    auto poDomain = std::unique_ptr<OGRFieldDomain>(
9273
0
        OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9274
0
    if (poDomain == nullptr)
9275
0
        return false;
9276
0
    std::string failureReason;
9277
0
    const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9278
0
        std::move(poDomain), failureReason);
9279
0
    if (ppszFailureReason)
9280
0
    {
9281
0
        *ppszFailureReason =
9282
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9283
0
    }
9284
0
    return bRet;
9285
0
}
9286
9287
/************************************************************************/
9288
/*                        DeleteFieldDomain()                           */
9289
/************************************************************************/
9290
9291
/** Removes a field domain from the dataset.
9292
 *
9293
 * Only a few drivers will support this operation.
9294
 *
9295
 * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9296
 * support this operation. A dataset having at least some support for this
9297
 * operation should report the ODsCDeleteFieldDomain dataset capability.
9298
 *
9299
 * Anticipated failures will not be emitted through the CPLError()
9300
 * infrastructure, but will be reported in the failureReason output parameter.
9301
 *
9302
 * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9303
 * default implementation of GetFieldDomainNames() to work correctly, or
9304
 * alternatively a specialized implementation of GetFieldDomainNames() should be
9305
 * implemented.
9306
 *
9307
 * @param name The domain name.
9308
 * @param failureReason      Output parameter. Will contain an error message if
9309
 *                           an error occurs.
9310
 * @return true in case of success.
9311
 * @since GDAL 3.5
9312
 */
9313
bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
9314
                                    std::string &failureReason)
9315
0
{
9316
0
    failureReason = "DeleteFieldDomain not supported by this driver";
9317
0
    return false;
9318
0
}
9319
9320
/************************************************************************/
9321
/*                  GDALDatasetDeleteFieldDomain()                      */
9322
/************************************************************************/
9323
9324
/** Removes a field domain from the dataset.
9325
 *
9326
 * Only a few drivers will support this operation.
9327
 *
9328
 * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9329
 * support this operation. A dataset having at least some support for this
9330
 * operation should report the ODsCDeleteFieldDomain dataset capability.
9331
 *
9332
 * Anticipated failures will not be emitted through the CPLError()
9333
 * infrastructure, but will be reported in the ppszFailureReason output
9334
 * parameter.
9335
 *
9336
 * @param hDS                Dataset handle.
9337
 * @param pszName            The domain name.
9338
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9339
 *                           an error occurs (*ppszFailureReason to be freed
9340
 *                           with CPLFree). May be NULL.
9341
 * @return true in case of success.
9342
 * @since GDAL 3.3
9343
 */
9344
bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
9345
                                  char **ppszFailureReason)
9346
0
{
9347
0
    VALIDATE_POINTER1(hDS, __func__, false);
9348
0
    VALIDATE_POINTER1(pszName, __func__, false);
9349
0
    std::string failureReason;
9350
0
    const bool bRet =
9351
0
        GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
9352
0
    if (ppszFailureReason)
9353
0
    {
9354
0
        *ppszFailureReason =
9355
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9356
0
    }
9357
0
    return bRet;
9358
0
}
9359
9360
/************************************************************************/
9361
/*                       UpdateFieldDomain()                            */
9362
/************************************************************************/
9363
9364
/** Updates an existing field domain by replacing its definition.
9365
 *
9366
 * The existing field domain with matching name will be replaced.
9367
 *
9368
 * Only a few drivers will support this operation, and some of them might only
9369
 * support it only for some types of field domains.
9370
 * At the time of writing (GDAL 3.5), only the Memory driver
9371
 * supports this operation. A dataset having at least some support for this
9372
 * operation should report the ODsCUpdateFieldDomain dataset capability.
9373
 *
9374
 * Anticipated failures will not be emitted through the CPLError()
9375
 * infrastructure, but will be reported in the failureReason output parameter.
9376
 *
9377
 * @param domain The domain definition.
9378
 * @param failureReason      Output parameter. Will contain an error message if
9379
 *                           an error occurs.
9380
 * @return true in case of success.
9381
 * @since GDAL 3.5
9382
 */
9383
bool GDALDataset::UpdateFieldDomain(
9384
    CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9385
    std::string &failureReason)
9386
0
{
9387
0
    failureReason = "UpdateFieldDomain not supported by this driver";
9388
0
    return false;
9389
0
}
9390
9391
/************************************************************************/
9392
/*                  GDALDatasetUpdateFieldDomain()                      */
9393
/************************************************************************/
9394
9395
/** Updates an existing field domain by replacing its definition.
9396
 *
9397
 * The existing field domain with matching name will be replaced.
9398
 *
9399
 * Only a few drivers will support this operation, and some of them might only
9400
 * support it only for some types of field domains.
9401
 * At the time of writing (GDAL 3.5), only the Memory driver
9402
 * supports this operation. A dataset having at least some support for this
9403
 * operation should report the ODsCUpdateFieldDomain dataset capability.
9404
 *
9405
 * Anticipated failures will not be emitted through the CPLError()
9406
 * infrastructure, but will be reported in the failureReason output parameter.
9407
 *
9408
 * @param hDS                Dataset handle.
9409
 * @param hFieldDomain       The domain definition. Contrary to the C++ version,
9410
 *                           the passed object is copied.
9411
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9412
 *                           an error occurs (*ppszFailureReason to be freed
9413
 *                           with CPLFree). May be NULL.
9414
 * @return true in case of success.
9415
 * @since GDAL 3.5
9416
 */
9417
bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
9418
                                  OGRFieldDomainH hFieldDomain,
9419
                                  char **ppszFailureReason)
9420
0
{
9421
0
    VALIDATE_POINTER1(hDS, __func__, false);
9422
0
    VALIDATE_POINTER1(hFieldDomain, __func__, false);
9423
0
    auto poDomain = std::unique_ptr<OGRFieldDomain>(
9424
0
        OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9425
0
    if (poDomain == nullptr)
9426
0
        return false;
9427
0
    std::string failureReason;
9428
0
    const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
9429
0
        std::move(poDomain), failureReason);
9430
0
    if (ppszFailureReason)
9431
0
    {
9432
0
        *ppszFailureReason =
9433
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9434
0
    }
9435
0
    return bRet;
9436
0
}
9437
9438
/************************************************************************/
9439
/*                        GetRelationshipNames()                        */
9440
/************************************************************************/
9441
9442
/** Returns a list of the names of all relationships stored in the dataset.
9443
 *
9444
 * @param papszOptions Driver specific options determining how relationships
9445
 * should be retrieved. Pass nullptr for default behavior.
9446
 *
9447
 * @return list of relationship names
9448
 * @since GDAL 3.6
9449
 */
9450
std::vector<std::string>
9451
GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
9452
0
{
9453
0
    return {};
9454
0
}
9455
9456
/************************************************************************/
9457
/*                     GDALDatasetGetRelationshipNames()                */
9458
/************************************************************************/
9459
9460
/** Returns a list of the names of all relationships stored in the dataset.
9461
 *
9462
 * This is the same as the C++ method GDALDataset::GetRelationshipNames().
9463
 *
9464
 * @param hDS Dataset handle.
9465
 * @param papszOptions Driver specific options determining how relationships
9466
 * should be retrieved. Pass nullptr for default behavior.
9467
 *
9468
 * @return list of relationship names, to be freed with CSLDestroy()
9469
 * @since GDAL 3.6
9470
 */
9471
char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
9472
                                       CSLConstList papszOptions)
9473
0
{
9474
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9475
0
    auto names =
9476
0
        GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
9477
0
    CPLStringList res;
9478
0
    for (const auto &name : names)
9479
0
    {
9480
0
        res.AddString(name.c_str());
9481
0
    }
9482
0
    return res.StealList();
9483
0
}
9484
9485
/************************************************************************/
9486
/*                        GetRelationship()                             */
9487
/************************************************************************/
9488
9489
/** Get a relationship from its name.
9490
 *
9491
 * @return the relationship, or nullptr if not found.
9492
 * @since GDAL 3.6
9493
 */
9494
const GDALRelationship *
9495
GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
9496
0
{
9497
0
    return nullptr;
9498
0
}
9499
9500
/************************************************************************/
9501
/*                      GDALDatasetGetRelationship()                    */
9502
/************************************************************************/
9503
9504
/** Get a relationship from its name.
9505
 *
9506
 * This is the same as the C++ method GDALDataset::GetRelationship().
9507
 *
9508
 * @param hDS Dataset handle.
9509
 * @param pszName Name of relationship.
9510
 * @return the relationship (ownership remains to the dataset), or nullptr if
9511
 * not found.
9512
 * @since GDAL 3.6
9513
 */
9514
GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
9515
                                             const char *pszName)
9516
0
{
9517
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9518
0
    VALIDATE_POINTER1(pszName, __func__, nullptr);
9519
0
    return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
9520
0
        GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
9521
0
}
9522
9523
/************************************************************************/
9524
/*                         AddRelationship()                            */
9525
/************************************************************************/
9526
9527
/** Add a relationship to the dataset.
9528
 *
9529
 * Only a few drivers will support this operation, and some of them might only
9530
 * support it only for some types of relationships.
9531
 *
9532
 * A dataset having at least some support for this
9533
 * operation should report the GDsCAddRelationship dataset capability.
9534
 *
9535
 * Anticipated failures will not be emitted through the CPLError()
9536
 * infrastructure, but will be reported in the failureReason output parameter.
9537
 *
9538
 * When adding a many-to-many relationship
9539
 * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9540
 * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
9541
 * the driver to create an appropriately named and structured mapping table.
9542
 * Some dataset formats require particular naming conventions and field
9543
 * structures for the mapping table, and delegating the construction of the
9544
 * mapping table to the driver will avoid these pitfalls.
9545
 *
9546
 * @param relationship The relationship definition.
9547
 * @param failureReason      Output parameter. Will contain an error message if
9548
 *                           an error occurs.
9549
 * @return true in case of success.
9550
 * @since GDAL 3.6
9551
 */
9552
bool GDALDataset::AddRelationship(
9553
    CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9554
    std::string &failureReason)
9555
0
{
9556
0
    failureReason = "AddRelationship not supported by this driver";
9557
0
    return false;
9558
0
}
9559
9560
/************************************************************************/
9561
/*                     GDALDatasetAddRelationship()                     */
9562
/************************************************************************/
9563
9564
/** Add a relationship to the dataset.
9565
 *
9566
 * Only a few drivers will support this operation, and some of them might only
9567
 * support it only for some types of relationships.
9568
 *
9569
 * A dataset having at least some support for this
9570
 * operation should report the GDsCAddRelationship dataset capability.
9571
 *
9572
 * Anticipated failures will not be emitted through the CPLError()
9573
 * infrastructure, but will be reported in the failureReason output parameter.
9574
 *
9575
 * When adding a many-to-many relationship
9576
 * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9577
 * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
9578
 * driver to create an appropriately named and structured mapping table. Some
9579
 * dataset formats require particular naming conventions and field structures
9580
 * for the mapping table, and delegating the construction of the mapping table
9581
 * to the driver will avoid these pitfalls.
9582
 *
9583
 * @param hDS                Dataset handle.
9584
 * @param hRelationship      The relationship definition. Contrary to the C++
9585
 * version, the passed object is copied.
9586
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9587
 *                           an error occurs (*ppszFailureReason to be freed
9588
 *                           with CPLFree). May be NULL.
9589
 * @return true in case of success.
9590
 * @since GDAL 3.6
9591
 */
9592
bool GDALDatasetAddRelationship(GDALDatasetH hDS,
9593
                                GDALRelationshipH hRelationship,
9594
                                char **ppszFailureReason)
9595
0
{
9596
0
    VALIDATE_POINTER1(hDS, __func__, false);
9597
0
    VALIDATE_POINTER1(hRelationship, __func__, false);
9598
0
    std::unique_ptr<GDALRelationship> poRelationship(
9599
0
        new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9600
0
    std::string failureReason;
9601
0
    const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
9602
0
        std::move(poRelationship), failureReason);
9603
0
    if (ppszFailureReason)
9604
0
    {
9605
0
        *ppszFailureReason =
9606
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9607
0
    }
9608
0
    return bRet;
9609
0
}
9610
9611
/************************************************************************/
9612
/*                        DeleteRelationship()                          */
9613
/************************************************************************/
9614
9615
/** Removes a relationship from the dataset.
9616
 *
9617
 * Only a few drivers will support this operation.
9618
 *
9619
 * A dataset having at least some support for this
9620
 * operation should report the GDsCDeleteRelationship dataset capability.
9621
 *
9622
 * Anticipated failures will not be emitted through the CPLError()
9623
 * infrastructure, but will be reported in the failureReason output parameter.
9624
 *
9625
 * @param name The relationship name.
9626
 * @param failureReason      Output parameter. Will contain an error message if
9627
 *                           an error occurs.
9628
 * @return true in case of success.
9629
 * @since GDAL 3.6
9630
 */
9631
bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
9632
                                     std::string &failureReason)
9633
0
{
9634
0
    failureReason = "DeleteRelationship not supported by this driver";
9635
0
    return false;
9636
0
}
9637
9638
/************************************************************************/
9639
/*                  GDALDatasetDeleteRelationship()                     */
9640
/************************************************************************/
9641
9642
/** Removes a relationship from the dataset.
9643
 *
9644
 * Only a few drivers will support this operation.
9645
 *
9646
 * A dataset having at least some support for this
9647
 * operation should report the GDsCDeleteRelationship dataset capability.
9648
 *
9649
 * Anticipated failures will not be emitted through the CPLError()
9650
 * infrastructure, but will be reported in the ppszFailureReason output
9651
 * parameter.
9652
 *
9653
 * @param hDS                Dataset handle.
9654
 * @param pszName            The relationship name.
9655
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9656
 *                           an error occurs (*ppszFailureReason to be freed
9657
 *                           with CPLFree). May be NULL.
9658
 * @return true in case of success.
9659
 * @since GDAL 3.6
9660
 */
9661
bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
9662
                                   char **ppszFailureReason)
9663
0
{
9664
0
    VALIDATE_POINTER1(hDS, __func__, false);
9665
0
    VALIDATE_POINTER1(pszName, __func__, false);
9666
0
    std::string failureReason;
9667
0
    const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
9668
0
        pszName, failureReason);
9669
0
    if (ppszFailureReason)
9670
0
    {
9671
0
        *ppszFailureReason =
9672
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9673
0
    }
9674
0
    return bRet;
9675
0
}
9676
9677
/************************************************************************/
9678
/*                       UpdateRelationship()                           */
9679
/************************************************************************/
9680
9681
/** Updates an existing relationship by replacing its definition.
9682
 *
9683
 * The existing relationship with matching name will be replaced.
9684
 *
9685
 * Only a few drivers will support this operation, and some of them might only
9686
 * support it only for some types of relationships.
9687
 * A dataset having at least some support for this
9688
 * operation should report the GDsCUpdateRelationship dataset capability.
9689
 *
9690
 * Anticipated failures will not be emitted through the CPLError()
9691
 * infrastructure, but will be reported in the failureReason output parameter.
9692
 *
9693
 * @param relationship   The relationship definition.
9694
 * @param failureReason  Output parameter. Will contain an error message if
9695
 *                       an error occurs.
9696
 * @return true in case of success.
9697
 * @since GDAL 3.6
9698
 */
9699
bool GDALDataset::UpdateRelationship(
9700
    CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9701
    std::string &failureReason)
9702
0
{
9703
0
    failureReason = "UpdateRelationship not supported by this driver";
9704
0
    return false;
9705
0
}
9706
9707
/************************************************************************/
9708
/*                  GDALDatasetUpdateRelationship()                     */
9709
/************************************************************************/
9710
9711
/** Updates an existing relationship by replacing its definition.
9712
 *
9713
 * The existing relationship with matching name will be replaced.
9714
 *
9715
 * Only a few drivers will support this operation, and some of them might only
9716
 * support it only for some types of relationships.
9717
 * A dataset having at least some support for this
9718
 * operation should report the GDsCUpdateRelationship dataset capability.
9719
 *
9720
 * Anticipated failures will not be emitted through the CPLError()
9721
 * infrastructure, but will be reported in the failureReason output parameter.
9722
 *
9723
 * @param hDS                Dataset handle.
9724
 * @param hRelationship      The relationship definition. Contrary to the C++
9725
 * version, the passed object is copied.
9726
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9727
 *                           an error occurs (*ppszFailureReason to be freed
9728
 *                           with CPLFree). May be NULL.
9729
 * @return true in case of success.
9730
 * @since GDAL 3.5
9731
 */
9732
bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
9733
                                   GDALRelationshipH hRelationship,
9734
                                   char **ppszFailureReason)
9735
0
{
9736
0
    VALIDATE_POINTER1(hDS, __func__, false);
9737
0
    VALIDATE_POINTER1(hRelationship, __func__, false);
9738
0
    std::unique_ptr<GDALRelationship> poRelationship(
9739
0
        new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9740
0
    std::string failureReason;
9741
0
    const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
9742
0
        std::move(poRelationship), failureReason);
9743
0
    if (ppszFailureReason)
9744
0
    {
9745
0
        *ppszFailureReason =
9746
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9747
0
    }
9748
0
    return bRet;
9749
0
}
9750
9751
/************************************************************************/
9752
/*                  GDALDatasetSetQueryLoggerFunc()                     */
9753
/************************************************************************/
9754
9755
/**
9756
 * Sets the SQL query logger callback.
9757
 *
9758
 * When supported by the driver, the callback will be called with
9759
 * the executed SQL text, the error message, the execution time in milliseconds,
9760
 * the number of records fetched/affected and the client status data.
9761
 *
9762
 * A value of -1 in the execution time or in the number of records indicates
9763
 * that the values are unknown.
9764
 *
9765
 * @param hDS                   Dataset handle.
9766
 * @param pfnQueryLoggerFunc    Callback function
9767
 * @param poQueryLoggerArg      Opaque client status data
9768
 * @return                      true in case of success.
9769
 * @since                       GDAL 3.7
9770
 */
9771
bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
9772
                                   GDALQueryLoggerFunc pfnQueryLoggerFunc,
9773
                                   void *poQueryLoggerArg)
9774
0
{
9775
0
    VALIDATE_POINTER1(hDS, __func__, false);
9776
0
    return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
9777
0
                                                            poQueryLoggerArg);
9778
0
}
9779
9780
//! @cond Doxygen_Suppress
9781
9782
/************************************************************************/
9783
/*                       SetEnableOverviews()                           */
9784
/************************************************************************/
9785
9786
void GDALDataset::SetEnableOverviews(bool bEnable)
9787
0
{
9788
0
    if (m_poPrivate)
9789
0
    {
9790
0
        m_poPrivate->m_bOverviewsEnabled = bEnable;
9791
0
    }
9792
0
}
9793
9794
/************************************************************************/
9795
/*                      AreOverviewsEnabled()                           */
9796
/************************************************************************/
9797
9798
bool GDALDataset::AreOverviewsEnabled() const
9799
0
{
9800
0
    return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
9801
0
}
9802
9803
/************************************************************************/
9804
/*                             IsAllBands()                             */
9805
/************************************************************************/
9806
9807
bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
9808
0
{
9809
0
    if (nBands != nBandCount)
9810
0
        return false;
9811
0
    if (panBandList)
9812
0
    {
9813
0
        for (int i = 0; i < nBandCount; ++i)
9814
0
        {
9815
0
            if (panBandList[i] != i + 1)
9816
0
                return false;
9817
0
        }
9818
0
    }
9819
0
    return true;
9820
0
}
9821
9822
//! @endcond
9823
9824
/************************************************************************/
9825
/*                       GetCompressionFormats()                        */
9826
/************************************************************************/
9827
9828
/** Return the compression formats that can be natively obtained for the
9829
 * window of interest and requested bands.
9830
 *
9831
 * For example, a tiled dataset may be able to return data in a compressed
9832
 * format if the window of interest matches exactly a tile. For some formats,
9833
 * drivers may also be able to merge several tiles together (not currently
9834
 * implemented though).
9835
 *
9836
 * Each format string is a pseudo MIME type, whose first part can be passed
9837
 * as the pszFormat argument of ReadCompressedData(), with additional
9838
 * parameters specified as key=value with a semi-colon separator.
9839
 *
9840
 * The amount and types of optional parameters passed after the MIME type is
9841
 * format dependent, and driver dependent (some drivers might not be able to
9842
 * return those extra information without doing a rather costly processing).
9843
 *
9844
 * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9845
 * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9846
 * consequently "JPEG" can be passed as the pszFormat argument of
9847
 * ReadCompressedData(). For JPEG, implementations can use the
9848
 * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9849
 * above from a JPEG codestream.
9850
 *
9851
 * Several values might be returned. For example,
9852
 * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9853
 * if the JPEGXL codestream includes a JPEG reconstruction box.
9854
 *
9855
 * In the general case this method will return an empty list.
9856
 *
9857
 * This is the same as C function GDALDatasetGetCompressionFormats().
9858
 *
9859
 * @param nXOff The pixel offset to the top left corner of the region
9860
 * of the band to be accessed.  This would be zero to start from the left side.
9861
 *
9862
 * @param nYOff The line offset to the top left corner of the region
9863
 * of the band to be accessed.  This would be zero to start from the top.
9864
 *
9865
 * @param nXSize The width of the region of the band to be accessed in pixels.
9866
 *
9867
 * @param nYSize The height of the region of the band to be accessed in lines.
9868
 *
9869
 * @param nBandCount the number of bands being requested.
9870
 *
9871
 * @param panBandList the list of nBandCount band numbers.
9872
 * Note band numbers are 1 based. This may be NULL to select the first
9873
 * nBandCount bands.
9874
 *
9875
 * @return a list of compatible formats (which may be empty)
9876
 *
9877
 * For example, to check if native compression format(s) are available on the
9878
 * whole image:
9879
 * \code{.cpp}
9880
 *   const CPLStringList aosFormats =
9881
 *      poDataset->GetCompressionFormats(0, 0,
9882
 *                                       poDataset->GetRasterXSize(),
9883
 *                                       poDataset->GetRasterYSize(),
9884
 *                                       poDataset->GetRasterCount(),
9885
 *                                       nullptr);
9886
 *   for( const char* pszFormat: aosFormats )
9887
 *   {
9888
 *      // Remove optional parameters and just print out the MIME type.
9889
 *      const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
9890
 *      printf("Found format %s\n, aosTokens[0]);
9891
 *   }
9892
 * \endcode
9893
 *
9894
 * @since GDAL 3.7
9895
 */
9896
CPLStringList
9897
GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
9898
                                   CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
9899
                                   CPL_UNUSED int nBandCount,
9900
                                   CPL_UNUSED const int *panBandList)
9901
0
{
9902
0
    return CPLStringList();
9903
0
}
9904
9905
/************************************************************************/
9906
/*                 GDALDatasetGetCompressionFormats()                   */
9907
/************************************************************************/
9908
9909
/** Return the compression formats that can be natively obtained for the
9910
 * window of interest and requested bands.
9911
 *
9912
 * For example, a tiled dataset may be able to return data in a compressed
9913
 * format if the window of interest matches exactly a tile. For some formats,
9914
 * drivers may also be able to merge several tiles together (not currently
9915
 * implemented though).
9916
 *
9917
 * Each format string is a pseudo MIME type, whose first part can be passed
9918
 * as the pszFormat argument of ReadCompressedData(), with additional
9919
 * parameters specified as key=value with a semi-colon separator.
9920
 *
9921
 * The amount and types of optional parameters passed after the MIME type is
9922
 * format dependent, and driver dependent (some drivers might not be able to
9923
 * return those extra information without doing a rather costly processing).
9924
 *
9925
 * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9926
 * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9927
 * consequently "JPEG" can be passed as the pszFormat argument of
9928
 * ReadCompressedData(). For JPEG, implementations can use the
9929
 * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9930
 * above from a JPEG codestream.
9931
 *
9932
 * Several values might be returned. For example,
9933
 * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9934
 * if the JPEGXL codestream includes a JPEG reconstruction box.
9935
 *
9936
 * In the general case this method will return an empty list.
9937
 *
9938
 * This is the same as C++ method GDALDataset::GetCompressionFormats().
9939
 *
9940
 * @param hDS Dataset handle.
9941
 *
9942
 * @param nXOff The pixel offset to the top left corner of the region
9943
 * of the band to be accessed.  This would be zero to start from the left side.
9944
 *
9945
 * @param nYOff The line offset to the top left corner of the region
9946
 * of the band to be accessed.  This would be zero to start from the top.
9947
 *
9948
 * @param nXSize The width of the region of the band to be accessed in pixels.
9949
 *
9950
 * @param nYSize The height of the region of the band to be accessed in lines.
9951
 *
9952
 * @param nBandCount the number of bands being requested.
9953
 *
9954
 * @param panBandList the list of nBandCount band numbers.
9955
 * Note band numbers are 1 based. This may be NULL to select the first
9956
 * nBandCount bands.
9957
 *
9958
 * @return a list of compatible formats (which may be empty) that should be
9959
 * freed with CSLDestroy(), or nullptr.
9960
 *
9961
 * @since GDAL 3.7
9962
 */
9963
char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
9964
                                        int nXSize, int nYSize, int nBandCount,
9965
                                        const int *panBandList)
9966
0
{
9967
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9968
0
    return GDALDataset::FromHandle(hDS)
9969
0
        ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
9970
0
                                panBandList)
9971
0
        .StealList();
9972
0
}
9973
9974
/************************************************************************/
9975
/*                         ReadCompressedData()                         */
9976
/************************************************************************/
9977
9978
/** Return the compressed content that can be natively obtained for the
9979
 * window of interest and requested bands.
9980
 *
9981
 * For example, a tiled dataset may be able to return data in compressed format
9982
 * if the window of interest matches exactly a tile. For some formats, drivers
9983
 * may also be example to merge several tiles together (not currently
9984
 * implemented though).
9985
 *
9986
 * The implementation should make sure that the content returned forms a valid
9987
 * standalone file. For example, for the GeoTIFF implementation of this method,
9988
 * when extracting a JPEG tile, the method will automatically add the content
9989
 * of the JPEG Huffman and/or quantization tables that might be stored in the
9990
 * TIFF JpegTables tag, and not in tile data itself.
9991
 *
9992
 * In the general case this method will return CE_Failure.
9993
 *
9994
 * This is the same as C function GDALDatasetReadCompressedData().
9995
 *
9996
 * @param pszFormat Requested compression format (e.g. "JPEG",
9997
 * "WEBP", "JXL"). This is the MIME type of one of the values
9998
 * returned by GetCompressionFormats(). The format string is designed to
9999
 * potentially include at a later point key=value optional parameters separated
10000
 * by a semi-colon character. At time of writing, none are implemented.
10001
 * ReadCompressedData() implementations should verify optional parameters and
10002
 * return CE_Failure if they cannot support one of them.
10003
 *
10004
 * @param nXOff The pixel offset to the top left corner of the region
10005
 * of the band to be accessed.  This would be zero to start from the left side.
10006
 *
10007
 * @param nYOff The line offset to the top left corner of the region
10008
 * of the band to be accessed.  This would be zero to start from the top.
10009
 *
10010
 * @param nXSize The width of the region of the band to be accessed in pixels.
10011
 *
10012
 * @param nYSize The height of the region of the band to be accessed in lines.
10013
 *
10014
 * @param nBandCount the number of bands being requested.
10015
 *
10016
 * @param panBandList the list of nBandCount band numbers.
10017
 * Note band numbers are 1 based. This may be NULL to select the first
10018
 * nBandCount bands.
10019
 *
10020
 * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10021
 * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10022
 * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10023
 * buffer will be filled with the compressed data, provided that pnBufferSize
10024
 * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10025
 * of *ppBuffer, is sufficiently large to hold the data.
10026
 * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10027
 * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10028
 * free it with VSIFree().
10029
 * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10030
 * but *pnBufferSize will be updated with an upper bound of the size that would
10031
 * be necessary to hold it (if pnBufferSize != nullptr).
10032
 *
10033
 * @param pnBufferSize Output buffer size, or nullptr.
10034
 * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10035
 * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10036
 * method is successful, *pnBufferSize will be updated with the actual size
10037
 * used.
10038
 *
10039
 * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10040
 * If ppszDetailedFormat is not nullptr, then, on success, the method will
10041
 * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10042
 * *ppszDetailedFormat might contain strings like
10043
 * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10044
 * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10045
 * The string will contain at least as much information as what
10046
 * GetCompressionFormats() returns, and potentially more when
10047
 * ppBuffer != nullptr.
10048
 *
10049
 * @return CE_None in case of success, CE_Failure otherwise.
10050
 *
10051
 * For example, to request JPEG content on the whole image and let GDAL deal
10052
 * with the buffer allocation.
10053
 * \code{.cpp}
10054
 *   void* pBuffer = nullptr;
10055
 *   size_t nBufferSize = 0;
10056
 *   CPLErr eErr =
10057
 *      poDataset->ReadCompressedData("JPEG",
10058
 *                                    0, 0,
10059
 *                                    poDataset->GetRasterXSize(),
10060
 *                                    poDataset->GetRasterYSize(),
10061
 *                                    poDataset->GetRasterCount(),
10062
 *                                    nullptr, // panBandList
10063
 *                                    &pBuffer,
10064
 *                                    &nBufferSize,
10065
 *                                    nullptr // ppszDetailedFormat
10066
 *                                   );
10067
 *   if (eErr == CE_None)
10068
 *   {
10069
 *       CPLAssert(pBuffer != nullptr);
10070
 *       CPLAssert(nBufferSize > 0);
10071
 *       VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
10072
 *       if (fp)
10073
 *       {
10074
 *           VSIFWriteL(pBuffer, nBufferSize, 1, fp);
10075
 *           VSIFCloseL(fp);
10076
 *       }
10077
 *       VSIFree(pBuffer);
10078
 *   }
10079
 * \endcode
10080
 *
10081
 * Or to manage the buffer allocation on your side:
10082
 * \code{.cpp}
10083
 *   size_t nUpperBoundBufferSize = 0;
10084
 *   CPLErr eErr =
10085
 *      poDataset->ReadCompressedData("JPEG",
10086
 *                                    0, 0,
10087
 *                                    poDataset->GetRasterXSize(),
10088
 *                                    poDataset->GetRasterYSize(),
10089
 *                                    poDataset->GetRasterCount(),
10090
 *                                    nullptr, // panBandList
10091
 *                                    nullptr, // ppBuffer,
10092
 *                                    &nUpperBoundBufferSize,
10093
 *                                    nullptr // ppszDetailedFormat
10094
 *                                   );
10095
 *   if (eErr == CE_None)
10096
 *   {
10097
 *       std::vector<uint8_t> myBuffer;
10098
 *       myBuffer.resize(nUpperBoundBufferSize);
10099
 *       void* pBuffer = myBuffer.data();
10100
 *       size_t nActualSize = nUpperBoundBufferSize;
10101
 *       char* pszDetailedFormat = nullptr;
10102
 *       // We also request detailed format, but we could have passed it to
10103
 *       // nullptr as well.
10104
 *       eErr =
10105
 *         poDataset->ReadCompressedData("JPEG",
10106
 *                                       0, 0,
10107
 *                                       poDataset->GetRasterXSize(),
10108
 *                                       poDataset->GetRasterYSize(),
10109
 *                                       poDataset->GetRasterCount(),
10110
 *                                       nullptr, // panBandList
10111
 *                                       &pBuffer,
10112
 *                                       &nActualSize,
10113
 *                                       &pszDetailedFormat);
10114
 *       if (eErr == CE_None)
10115
 *       {
10116
 *          CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10117
 *          CPLAssert(nActualSize <= nUpperBoundBufferSize);
10118
 *          myBuffer.resize(nActualSize);
10119
 *          // do something useful
10120
 *          VSIFree(pszDetailedFormat);
10121
 *       }
10122
 *   }
10123
 * \endcode
10124
 *
10125
 * @since GDAL 3.7
10126
 */
10127
CPLErr GDALDataset::ReadCompressedData(
10128
    CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10129
    CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10130
    CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10131
    CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10132
    CPL_UNUSED char **ppszDetailedFormat)
10133
0
{
10134
0
    return CE_Failure;
10135
0
}
10136
10137
/************************************************************************/
10138
/*                  GDALDatasetReadCompressedData()                     */
10139
/************************************************************************/
10140
10141
/** Return the compressed content that can be natively obtained for the
10142
 * window of interest and requested bands.
10143
 *
10144
 * For example, a tiled dataset may be able to return data in compressed format
10145
 * if the window of interest matches exactly a tile. For some formats, drivers
10146
 * may also be example to merge several tiles together (not currently
10147
 * implemented though).
10148
 *
10149
 * The implementation should make sure that the content returned forms a valid
10150
 * standalone file. For example, for the GeoTIFF implementation of this method,
10151
 * when extracting a JPEG tile, the method will automatically adds the content
10152
 * of the JPEG Huffman and/or quantization tables that might be stored in the
10153
 * TIFF JpegTables tag, and not in tile data itself.
10154
 *
10155
 * In the general case this method will return CE_Failure.
10156
 *
10157
 * This is the same as C++ method GDALDataset:ReadCompressedData().
10158
 *
10159
 * @param hDS Dataset handle.
10160
 *
10161
 * @param pszFormat Requested compression format (e.g. "JPEG",
10162
 * "WEBP", "JXL"). This is the MIME type of one of the values
10163
 * returned by GetCompressionFormats(). The format string is designed to
10164
 * potentially include at a later point key=value optional parameters separated
10165
 * by a semi-colon character. At time of writing, none are implemented.
10166
 * ReadCompressedData() implementations should verify optional parameters and
10167
 * return CE_Failure if they cannot support one of them.
10168
 *
10169
 * @param nXOff The pixel offset to the top left corner of the region
10170
 * of the band to be accessed.  This would be zero to start from the left side.
10171
 *
10172
 * @param nYOff The line offset to the top left corner of the region
10173
 * of the band to be accessed.  This would be zero to start from the top.
10174
 *
10175
 * @param nXSize The width of the region of the band to be accessed in pixels.
10176
 *
10177
 * @param nYSize The height of the region of the band to be accessed in lines.
10178
 *
10179
 * @param nBandCount the number of bands being requested.
10180
 *
10181
 * @param panBandList the list of nBandCount band numbers.
10182
 * Note band numbers are 1 based. This may be NULL to select the first
10183
 * nBandCount bands.
10184
 *
10185
 * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10186
 * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10187
 * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10188
 * buffer will be filled with the compressed data, provided that pnBufferSize
10189
 * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10190
 * of *ppBuffer, is sufficiently large to hold the data.
10191
 * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10192
 * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10193
 * free it with VSIFree().
10194
 * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10195
 * but *pnBufferSize will be updated with an upper bound of the size that would
10196
 * be necessary to hold it (if pnBufferSize != nullptr).
10197
 *
10198
 * @param pnBufferSize Output buffer size, or nullptr.
10199
 * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10200
 * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10201
 * method is successful, *pnBufferSize will be updated with the actual size
10202
 * used.
10203
 *
10204
 * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10205
 * If ppszDetailedFormat is not nullptr, then, on success, the method will
10206
 * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10207
 * *ppszDetailedFormat might contain strings like
10208
 * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10209
 * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10210
 * The string will contain at least as much information as what
10211
 * GetCompressionFormats() returns, and potentially more when
10212
 * ppBuffer != nullptr.
10213
 *
10214
 * @return CE_None in case of success, CE_Failure otherwise.
10215
 *
10216
 * @since GDAL 3.7
10217
 */
10218
CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10219
                                     int nXOff, int nYOff, int nXSize,
10220
                                     int nYSize, int nBandCount,
10221
                                     const int *panBandList, void **ppBuffer,
10222
                                     size_t *pnBufferSize,
10223
                                     char **ppszDetailedFormat)
10224
0
{
10225
0
    VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10226
0
    return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10227
0
        pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10228
0
        ppBuffer, pnBufferSize, ppszDetailedFormat);
10229
0
}
10230
10231
/************************************************************************/
10232
/*                           CanBeCloned()                              */
10233
/************************************************************************/
10234
10235
//! @cond Doxygen_Suppress
10236
10237
/** This method is called by GDALThreadSafeDataset::Create() to determine if
10238
 * it is possible to create a thread-safe wrapper for a dataset, which involves
10239
 * the ability to Clone() it.
10240
 *
10241
 * Implementations of this method must be thread-safe.
10242
 *
10243
 * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10244
 *                    expressing the intended use for thread-safety.
10245
 *                    Currently, the only valid scope is in the base
10246
 *                    implementation is GDAL_OF_RASTER.
10247
 * @param bCanShareState Determines if cloned datasets are allowed to share
10248
 *                       state with the dataset they have been cloned from.
10249
 *                       If set to true, the dataset from which they have been
10250
 *                       cloned from must remain opened during the lifetime of
10251
 *                       its clones.
10252
 * @return true if the Clone() method is expected to succeed with the same values
10253
 *         of nScopeFlags and bCanShareState.
10254
 */
10255
bool GDALDataset::CanBeCloned(int nScopeFlags,
10256
                              [[maybe_unused]] bool bCanShareState) const
10257
0
{
10258
0
    return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
10259
0
}
10260
10261
//! @endcond
10262
10263
/************************************************************************/
10264
/*                               Clone()                                */
10265
/************************************************************************/
10266
10267
//! @cond Doxygen_Suppress
10268
10269
/** This method "clones" the current dataset, that is it returns a new instance
10270
 * that is opened on the same underlying "file".
10271
 *
10272
 * The base implementation uses GDALDataset::Open() to re-open the dataset.
10273
 * The MEM driver has a specialized implementation that returns a new instance,
10274
 * but which shares the same memory buffer as this.
10275
 *
10276
 * Implementations of this method must be thread-safe.
10277
 *
10278
 * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10279
 *                    expressing the intended use for thread-safety.
10280
 *                    Currently, the only valid scope is in the base
10281
 *                    implementation is GDAL_OF_RASTER.
10282
 * @param bCanShareState Determines if cloned datasets are allowed to share
10283
 *                       state with the dataset they have been cloned from.
10284
 *                       If set to true, the dataset from which they have been
10285
 *                       cloned from must remain opened during the lifetime of
10286
 *                       its clones.
10287
 * @return a new instance, or nullptr in case of error.
10288
 */
10289
std::unique_ptr<GDALDataset>
10290
GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
10291
0
{
10292
0
    CPLStringList aosAllowedDrivers;
10293
0
    if (poDriver)
10294
0
        aosAllowedDrivers.AddString(poDriver->GetDescription());
10295
0
    return std::unique_ptr<GDALDataset>(GDALDataset::Open(
10296
0
        GetDescription(),
10297
0
        nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
10298
0
        aosAllowedDrivers.List(), papszOpenOptions));
10299
0
}
10300
10301
//! @endcond
10302
10303
/************************************************************************/
10304
/*                    GeolocationToPixelLine()                          */
10305
/************************************************************************/
10306
10307
/** Transform georeferenced coordinates to pixel/line coordinates.
10308
 *
10309
 * When poSRS is null, those georeferenced coordinates (dfGeolocX, dfGeolocY)
10310
 * must be in the "natural" SRS of the dataset, that is the one returned by
10311
 * GetSpatialRef() if there is a geotransform, GetGCPSpatialRef() if there are
10312
 * GCPs, WGS 84 if there are RPC coefficients, or the SRS of the geolocation
10313
 * array (generally WGS 84) if there is a geolocation array.
10314
 * If that natural SRS is a geographic one, dfGeolocX must be a longitude, and
10315
 * dfGeolocY a latitude. If that natural SRS is a projected one, dfGeolocX must
10316
 * be a easting, and dfGeolocY a northing.
10317
 *
10318
 * When poSRS is set to a non-null value, (dfGeolocX, dfGeolocY) must be
10319
 * expressed in that CRS, and that tuple must be conformant with the
10320
 * data-axis-to-crs-axis setting of poSRS, that is the one returned by
10321
 * the OGRSpatialReference::GetDataAxisToSRSAxisMapping(). If you want to be sure
10322
 * of the axis order, then make sure to call poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)
10323
 * before calling this method, and in that case, dfGeolocX must be a longitude
10324
 * or an easting value, and dfGeolocX a latitude or a northing value.
10325
 *
10326
 * This method uses GDALCreateGenImgProjTransformer2() underneath.
10327
 *
10328
 * @param dfGeolocX X coordinate of the position (longitude or easting if poSRS
10329
 * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10330
 * where interpolation should be done.
10331
 * @param dfGeolocY Y coordinate of the position (latitude or northing if poSRS
10332
 * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10333
 * where interpolation should be done.
10334
 * @param poSRS If set, override the natural CRS in which dfGeolocX, dfGeolocY are expressed
10335
 * @param[out] pdfPixel Pointer to the variable where to the store the pixel/column coordinate.
10336
 * @param[out] pdfLine Pointer to the variable where to the store the line coordinate.
10337
 * @param papszTransformerOptions Options accepted by GDALCreateGenImgProjTransformer2(), or nullptr.
10338
 *
10339
 * @return CE_None on success, or an error code on failure.
10340
 * @since GDAL 3.11
10341
 */
10342
10343
CPLErr
10344
GDALDataset::GeolocationToPixelLine(double dfGeolocX, double dfGeolocY,
10345
                                    const OGRSpatialReference *poSRS,
10346
                                    double *pdfPixel, double *pdfLine,
10347
                                    CSLConstList papszTransformerOptions) const
10348
0
{
10349
0
    CPLStringList aosTO(papszTransformerOptions);
10350
10351
0
    if (poSRS)
10352
0
    {
10353
0
        const char *const apszOptions[] = {"FORMAT=WKT2", nullptr};
10354
0
        const std::string osWKT = poSRS->exportToWkt(apszOptions);
10355
0
        aosTO.SetNameValue("DST_SRS", osWKT.c_str());
10356
0
        const auto eAxisMappingStrategy = poSRS->GetAxisMappingStrategy();
10357
0
        if (eAxisMappingStrategy == OAMS_TRADITIONAL_GIS_ORDER)
10358
0
            aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10359
0
                               "TRADITIONAL_GIS_ORDER");
10360
0
        else if (eAxisMappingStrategy == OAMS_AUTHORITY_COMPLIANT)
10361
0
            aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10362
0
                               "AUTHORITY_COMPLIANT");
10363
0
        else
10364
0
        {
10365
0
            const auto &anValues = poSRS->GetDataAxisToSRSAxisMapping();
10366
0
            std::string osVal;
10367
0
            for (int v : anValues)
10368
0
            {
10369
0
                if (!osVal.empty())
10370
0
                    osVal += ',';
10371
0
                osVal += std::to_string(v);
10372
0
            }
10373
0
            aosTO.SetNameValue("DST_SRS_DATA_AXIS_TO_SRS_AXIS_MAPPING",
10374
0
                               osVal.c_str());
10375
0
        }
10376
0
    }
10377
10378
0
    auto hTransformer = GDALCreateGenImgProjTransformer2(
10379
0
        GDALDataset::ToHandle(const_cast<GDALDataset *>(this)), nullptr,
10380
0
        aosTO.List());
10381
0
    if (hTransformer == nullptr)
10382
0
    {
10383
0
        return CE_Failure;
10384
0
    }
10385
10386
0
    double z = 0;
10387
0
    int bSuccess = 0;
10388
0
    GDALGenImgProjTransform(hTransformer, TRUE, 1, &dfGeolocX, &dfGeolocY, &z,
10389
0
                            &bSuccess);
10390
0
    GDALDestroyTransformer(hTransformer);
10391
0
    if (bSuccess)
10392
0
    {
10393
0
        if (pdfPixel)
10394
0
            *pdfPixel = dfGeolocX;
10395
0
        if (pdfLine)
10396
0
            *pdfLine = dfGeolocY;
10397
0
        return CE_None;
10398
0
    }
10399
0
    else
10400
0
    {
10401
0
        return CE_Failure;
10402
0
    }
10403
0
}
10404
10405
/************************************************************************/
10406
/*                  GDALDatasetGeolocationToPixelLine()                 */
10407
/************************************************************************/
10408
10409
/** Transform georeferenced coordinates to pixel/line coordinates.
10410
 *
10411
 * @see GDALDataset::GeolocationToPixelLine()
10412
 * @since GDAL 3.11
10413
 */
10414
10415
CPLErr GDALDatasetGeolocationToPixelLine(GDALDatasetH hDS, double dfGeolocX,
10416
                                         double dfGeolocY,
10417
                                         OGRSpatialReferenceH hSRS,
10418
                                         double *pdfPixel, double *pdfLine,
10419
                                         CSLConstList papszTransformerOptions)
10420
0
{
10421
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGeolocationToPixelLine", CE_Failure);
10422
10423
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
10424
0
    return poDS->GeolocationToPixelLine(
10425
0
        dfGeolocX, dfGeolocY, OGRSpatialReference::FromHandle(hSRS), pdfPixel,
10426
0
        pdfLine, papszTransformerOptions);
10427
0
}
10428
10429
/************************************************************************/
10430
/*                  ReportUpdateNotSupportedByDriver()                  */
10431
/************************************************************************/
10432
10433
//! @cond Doxygen_Suppress
10434
10435
/* static */
10436
void GDALDataset::ReportUpdateNotSupportedByDriver(const char *pszDriverName)
10437
0
{
10438
0
    CPLError(CE_Failure, CPLE_NotSupported,
10439
0
             "The %s driver does not support update access to existing "
10440
0
             "datasets.",
10441
0
             pszDriverName);
10442
0
}
10443
10444
//! @endcond
10445
10446
/************************************************************************/
10447
/*                         BuildFilename()                              */
10448
/************************************************************************/
10449
10450
/** Generates a filename, potentially relative to another one.
10451
 *
10452
 * Given the path to a reference directory, and a path to a file
10453
 * referenced from it, build a path to the file that the current application
10454
 * can use. If the file path is already absolute, rather than relative, or if
10455
 * bRelativeToReferencePath is false, then the filename of interest will be
10456
 * returned unaltered.
10457
 *
10458
 * This is enhanced version of CPLProjectRelativeFilenameSafe() that takes
10459
 * into account the subdataset syntax.
10460
 *
10461
 * Examples:
10462
 * \code{.cpp}
10463
 * BuildFilename("tmp/abc.gif", "abc/def", true) == "abc/def/tmp/abc.gif"
10464
 * BuildFilename("../abc.gif", "/abc/def") == "/abc/abc.gif"
10465
 * BuildFilename("abc.gif", "C:\WIN", true) == "C:\WIN\abc.gif"
10466
 * BuildFilename("abc.gif", "C:\WIN", false) == "abc.gif"
10467
 * BuildFilename("/home/even/foo.tif", "/home/even/workdir", true) == "/home/even/foo.tif"
10468
 * \endcode
10469
 *
10470
 * @param pszFilename Filename of interest.
10471
 * @param pszReferencePath Path to a reference directory.
10472
 * @param bRelativeToReferencePath Whether pszFilename, if a relative path, is
10473
 *                                 relative to pszReferencePath
10474
 * @since 3.11
10475
 */
10476
10477
/* static */
10478
std::string GDALDataset::BuildFilename(const char *pszFilename,
10479
                                       const char *pszReferencePath,
10480
                                       bool bRelativeToReferencePath)
10481
0
{
10482
0
    std::string osSrcDSName;
10483
0
    if (pszReferencePath != nullptr && bRelativeToReferencePath)
10484
0
    {
10485
        // Try subdatasetinfo API first
10486
        // Note: this will become the only branch when subdatasetinfo will become
10487
        //       available for NITF_IM, RASTERLITE and TILEDB
10488
0
        const auto oSubDSInfo{GDALGetSubdatasetInfo(pszFilename)};
10489
0
        if (oSubDSInfo && !oSubDSInfo->GetPathComponent().empty())
10490
0
        {
10491
0
            auto path{oSubDSInfo->GetPathComponent()};
10492
0
            osSrcDSName = oSubDSInfo->ModifyPathComponent(
10493
0
                CPLProjectRelativeFilenameSafe(pszReferencePath, path.c_str())
10494
0
                    .c_str());
10495
0
            GDALDestroySubdatasetInfo(oSubDSInfo);
10496
0
        }
10497
0
        else
10498
0
        {
10499
0
            bool bDone = false;
10500
0
            for (const char *pszSyntax : apszSpecialSubDatasetSyntax)
10501
0
            {
10502
0
                CPLString osPrefix(pszSyntax);
10503
0
                osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
10504
0
                if (pszSyntax[osPrefix.size()] == '"')
10505
0
                    osPrefix += '"';
10506
0
                if (EQUALN(pszFilename, osPrefix, osPrefix.size()))
10507
0
                {
10508
0
                    if (STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}"))
10509
0
                    {
10510
0
                        const char *pszLastPart = strrchr(pszFilename, ':') + 1;
10511
                        // CSV:z:/foo.xyz
10512
0
                        if ((pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
10513
0
                            pszLastPart - pszFilename >= 3 &&
10514
0
                            pszLastPart[-3] == ':')
10515
0
                        {
10516
0
                            pszLastPart -= 2;
10517
0
                        }
10518
0
                        CPLString osPrefixFilename = pszFilename;
10519
0
                        osPrefixFilename.resize(pszLastPart - pszFilename);
10520
0
                        osSrcDSName = osPrefixFilename +
10521
0
                                      CPLProjectRelativeFilenameSafe(
10522
0
                                          pszReferencePath, pszLastPart);
10523
0
                        bDone = true;
10524
0
                    }
10525
0
                    else if (STARTS_WITH_CI(pszSyntax + osPrefix.size(),
10526
0
                                            "{FILENAME}"))
10527
0
                    {
10528
0
                        CPLString osFilename(pszFilename + osPrefix.size());
10529
0
                        size_t nPos = 0;
10530
0
                        if (osFilename.size() >= 3 && osFilename[1] == ':' &&
10531
0
                            (osFilename[2] == '\\' || osFilename[2] == '/'))
10532
0
                            nPos = 2;
10533
0
                        nPos = osFilename.find(
10534
0
                            pszSyntax[osPrefix.size() + strlen("{FILENAME}")],
10535
0
                            nPos);
10536
0
                        if (nPos != std::string::npos)
10537
0
                        {
10538
0
                            const CPLString osSuffix = osFilename.substr(nPos);
10539
0
                            osFilename.resize(nPos);
10540
0
                            osSrcDSName = osPrefix +
10541
0
                                          CPLProjectRelativeFilenameSafe(
10542
0
                                              pszReferencePath, osFilename) +
10543
0
                                          osSuffix;
10544
0
                            bDone = true;
10545
0
                        }
10546
0
                    }
10547
0
                    break;
10548
0
                }
10549
0
            }
10550
0
            if (!bDone)
10551
0
            {
10552
0
                std::string osReferencePath = pszReferencePath;
10553
0
                if (!CPLIsFilenameRelative(pszReferencePath))
10554
0
                {
10555
                    // Simplify path by replacing "foo/a/../b" with "foo/b"
10556
0
                    while (STARTS_WITH(pszFilename, "../"))
10557
0
                    {
10558
0
                        osReferencePath =
10559
0
                            CPLGetPathSafe(osReferencePath.c_str());
10560
0
                        pszFilename += strlen("../");
10561
0
                    }
10562
0
                }
10563
10564
0
                osSrcDSName = CPLProjectRelativeFilenameSafe(
10565
0
                    osReferencePath.c_str(), pszFilename);
10566
0
            }
10567
0
        }
10568
0
    }
10569
0
    else
10570
0
    {
10571
0
        osSrcDSName = pszFilename;
10572
0
    }
10573
0
    return osSrcDSName;
10574
0
}