Coverage Report

Created: 2025-06-22 06:59

/src/gdal/gcore/gdaldataset.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  GDAL Core
4
 * Purpose:  Base class for raster file formats.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 1998, 2003, Frank Warmerdam
9
 * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "cpl_port.h"
15
#include "gdal.h"
16
#include "gdal_priv.h"
17
18
#include <array>
19
#include <climits>
20
#include <cstdarg>
21
#include <cstdio>
22
#include <cstdlib>
23
#include <cstring>
24
#include <algorithm>
25
#include <map>
26
#include <mutex>
27
#include <new>
28
#include <set>
29
#include <string>
30
#include <utility>
31
32
#include "cpl_conv.h"
33
#include "cpl_error.h"
34
#include "cpl_hash_set.h"
35
#include "cpl_multiproc.h"
36
#include "cpl_progress.h"
37
#include "cpl_string.h"
38
#include "cpl_vsi.h"
39
#include "cpl_vsi_error.h"
40
#include "gdal_alg.h"
41
#include "ogr_api.h"
42
#include "ogr_attrind.h"
43
#include "ogr_core.h"
44
#include "ogr_feature.h"
45
#include "ogr_featurestyle.h"
46
#include "ogr_gensql.h"
47
#include "ogr_geometry.h"
48
#include "ogr_p.h"
49
#include "ogr_spatialref.h"
50
#include "ogr_srs_api.h"
51
#include "ograpispy.h"
52
#include "ogrsf_frmts.h"
53
#include "ogrunionlayer.h"
54
#include "ogr_swq.h"
55
56
#include "../frmts/derived/derivedlist.h"
57
58
#ifdef SQLITE_ENABLED
59
#include "../sqlite/ogrsqliteexecutesql.h"
60
#endif
61
62
extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
63
64
CPL_C_START
65
GDALAsyncReader *GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff,
66
                                           int nYOff, int nXSize, int nYSize,
67
                                           void *pBuf, int nBufXSize,
68
                                           int nBufYSize, GDALDataType eBufType,
69
                                           int nBandCount, int *panBandMap,
70
                                           int nPixelSpace, int nLineSpace,
71
                                           int nBandSpace, char **papszOptions);
72
CPL_C_END
73
74
enum class GDALAllowReadWriteMutexState
75
{
76
    RW_MUTEX_STATE_UNKNOWN,
77
    RW_MUTEX_STATE_ALLOWED,
78
    RW_MUTEX_STATE_DISABLED
79
};
80
81
const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
82
const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
83
84
class GDALDataset::Private
85
{
86
    CPL_DISALLOW_COPY_ASSIGN(Private)
87
88
  public:
89
    CPLMutex *hMutex = nullptr;
90
    std::map<GIntBig, int> oMapThreadToMutexTakenCount{};
91
#ifdef DEBUG_EXTRA
92
    std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved{};
93
#endif
94
    GDALAllowReadWriteMutexState eStateReadWriteMutex =
95
        GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN;
96
    int nCurrentLayerIdx = 0;
97
    int nLayerCount = -1;
98
    GIntBig nFeatureReadInLayer = 0;
99
    GIntBig nFeatureReadInDataset = 0;
100
    GIntBig nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
101
    GIntBig nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
102
    OGRLayer *poCurrentLayer = nullptr;
103
104
    std::mutex m_oMutexWKT{};
105
106
    char *m_pszWKTCached = nullptr;
107
    OGRSpatialReference *m_poSRSCached = nullptr;
108
    char *m_pszWKTGCPCached = nullptr;
109
    OGRSpatialReference *m_poSRSGCPCached = nullptr;
110
111
    GDALDataset *poParentDataset = nullptr;
112
113
    bool m_bOverviewsEnabled = true;
114
115
    std::vector<int>
116
        m_anBandMap{};  // used by RasterIO(). Values are 1, 2, etc.
117
118
0
    Private() = default;
119
};
120
121
struct SharedDatasetCtxt
122
{
123
    // PID of the thread that mark the dataset as shared
124
    // This may not be the actual PID, but the responsiblePID.
125
    GIntBig nPID;
126
    char *pszDescription;
127
    char *pszConcatenatedOpenOptions;
128
    int nOpenFlags;
129
130
    GDALDataset *poDS;
131
};
132
133
// Set of datasets opened as shared datasets (with GDALOpenShared)
134
// The values in the set are of type SharedDatasetCtxt.
135
static CPLHashSet *phSharedDatasetSet = nullptr;
136
137
// Set of all datasets created in the constructor of GDALDataset.
138
// In the case of a shared dataset, memorize the PID of the thread
139
// that marked the dataset as shared, so that we can remove it from
140
// the phSharedDatasetSet in the destructor of the dataset, even
141
// if GDALClose is called from a different thread.
142
static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = nullptr;
143
144
static CPLMutex *hDLMutex = nullptr;
145
146
// Static array of all datasets. Used by GDALGetOpenDatasets.
147
// Not thread-safe. See GDALGetOpenDatasets.
148
static GDALDataset **ppDatasets = nullptr;
149
150
static unsigned long GDALSharedDatasetHashFunc(const void *elt)
151
0
{
152
0
    const SharedDatasetCtxt *psStruct =
153
0
        static_cast<const SharedDatasetCtxt *>(elt);
154
0
    return static_cast<unsigned long>(
155
0
        CPLHashSetHashStr(psStruct->pszDescription) ^
156
0
        CPLHashSetHashStr(psStruct->pszConcatenatedOpenOptions) ^
157
0
        psStruct->nOpenFlags ^ psStruct->nPID);
158
0
}
159
160
static int GDALSharedDatasetEqualFunc(const void *elt1, const void *elt2)
161
0
{
162
0
    const SharedDatasetCtxt *psStruct1 =
163
0
        static_cast<const SharedDatasetCtxt *>(elt1);
164
0
    const SharedDatasetCtxt *psStruct2 =
165
0
        static_cast<const SharedDatasetCtxt *>(elt2);
166
0
    return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
167
0
           strcmp(psStruct1->pszConcatenatedOpenOptions,
168
0
                  psStruct2->pszConcatenatedOpenOptions) == 0 &&
169
0
           psStruct1->nPID == psStruct2->nPID &&
170
0
           psStruct1->nOpenFlags == psStruct2->nOpenFlags;
171
0
}
172
173
static void GDALSharedDatasetFreeFunc(void *elt)
174
0
{
175
0
    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
176
0
    CPLFree(psStruct->pszDescription);
177
0
    CPLFree(psStruct->pszConcatenatedOpenOptions);
178
0
    CPLFree(psStruct);
179
0
}
180
181
static std::string
182
GDALSharedDatasetConcatenateOpenOptions(CSLConstList papszOpenOptions)
183
0
{
184
0
    std::string osStr;
185
0
    for (const char *pszOption : cpl::Iterate(papszOpenOptions))
186
0
        osStr += pszOption;
187
0
    return osStr;
188
0
}
189
190
/************************************************************************/
191
/* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
192
/************************************************************************/
193
194
// The open-shared mutex must be used by the ProxyPool too.
195
CPLMutex **GDALGetphDLMutex()
196
0
{
197
0
    return &hDLMutex;
198
0
}
199
200
// The current thread will act in the behalf of the thread of PID
201
// responsiblePID.
202
void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
203
0
{
204
0
    GIntBig *pResponsiblePID =
205
0
        static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
206
0
    if (pResponsiblePID == nullptr)
207
0
    {
208
0
        pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
209
0
        CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
210
0
    }
211
0
    *pResponsiblePID = responsiblePID;
212
0
}
213
214
// Get the PID of the thread that the current thread will act in the behalf of
215
// By default : the current thread acts in the behalf of itself.
216
GIntBig GDALGetResponsiblePIDForCurrentThread()
217
0
{
218
0
    GIntBig *pResponsiblePID =
219
0
        static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
220
0
    if (pResponsiblePID == nullptr)
221
0
        return CPLGetPID();
222
0
    return *pResponsiblePID;
223
0
}
224
225
/************************************************************************/
226
/* ==================================================================== */
227
/*                             GDALDataset                              */
228
/* ==================================================================== */
229
/************************************************************************/
230
231
/**
232
 * \class GDALDataset "gdal_priv.h"
233
 *
234
 * A dataset encapsulating one or more raster bands.  Details are further
235
 * discussed in the <a href="https://gdal.org/user/raster_data_model.html">GDAL
236
 * Raster Data Model</a>.
237
 *
238
 * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
239
 * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
240
 * dataset.
241
 */
242
243
/************************************************************************/
244
/*                            GDALDataset()                             */
245
/************************************************************************/
246
247
//! @cond Doxygen_Suppress
248
GDALDataset::GDALDataset()
249
0
    : GDALDataset(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")))
250
0
{
251
0
}
252
253
GDALDataset::GDALDataset(int bForceCachedIOIn)
254
0
    : bForceCachedIO(CPL_TO_BOOL(bForceCachedIOIn)),
255
0
      m_poPrivate(new(std::nothrow) GDALDataset::Private)
256
0
{
257
0
}
258
259
//! @endcond
260
261
/************************************************************************/
262
/*                            ~GDALDataset()                            */
263
/************************************************************************/
264
265
/**
266
 * \brief Destroy an open GDALDataset.
267
 *
268
 * This is the accepted method of closing a GDAL dataset and deallocating
269
 * all resources associated with it.
270
 *
271
 * Equivalent of the C callable GDALClose().  Except that GDALClose() first
272
 * decrements the reference count, and then closes only if it has dropped to
273
 * zero.
274
 *
275
 * For Windows users, it is not recommended to use the delete operator on the
276
 * dataset object because of known issues when allocating and freeing memory
277
 * across module boundaries. Calling GDALClose() is then a better option.
278
 */
279
280
GDALDataset::~GDALDataset()
281
282
0
{
283
    // we don't want to report destruction of datasets that
284
    // were never really open or meant as internal
285
0
    if (!bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")))
286
0
    {
287
0
        if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
288
0
            CPLDebug("GDAL",
289
0
                     "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
290
0
                     GetDescription(), this, static_cast<int>(CPLGetPID()),
291
0
                     static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
292
0
        else
293
0
            CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
294
0
    }
295
296
0
    if (IsMarkedSuppressOnClose())
297
0
    {
298
0
        if (poDriver == nullptr ||
299
            // Someone issuing Create("foo.tif") on a
300
            // memory driver doesn't expect files with those names to be deleted
301
            // on a file system...
302
            // This is somewhat messy. Ideally there should be a way for the
303
            // driver to overload the default behavior
304
0
            (!EQUAL(poDriver->GetDescription(), "MEM") &&
305
0
             !EQUAL(poDriver->GetDescription(), "Memory")))
306
0
        {
307
0
            VSIUnlink(GetDescription());
308
0
        }
309
0
    }
310
311
    /* -------------------------------------------------------------------- */
312
    /*      Remove dataset from the "open" dataset list.                    */
313
    /* -------------------------------------------------------------------- */
314
0
    if (!bIsInternal)
315
0
    {
316
0
        CPLMutexHolderD(&hDLMutex);
317
0
        if (poAllDatasetMap)
318
0
        {
319
0
            std::map<GDALDataset *, GIntBig>::iterator oIter =
320
0
                poAllDatasetMap->find(this);
321
0
            CPLAssert(oIter != poAllDatasetMap->end());
322
323
0
            UnregisterFromSharedDataset();
324
325
0
            poAllDatasetMap->erase(oIter);
326
327
0
            if (poAllDatasetMap->empty())
328
0
            {
329
0
                delete poAllDatasetMap;
330
0
                poAllDatasetMap = nullptr;
331
0
                if (phSharedDatasetSet)
332
0
                {
333
0
                    CPLHashSetDestroy(phSharedDatasetSet);
334
0
                }
335
0
                phSharedDatasetSet = nullptr;
336
0
                CPLFree(ppDatasets);
337
0
                ppDatasets = nullptr;
338
0
            }
339
0
        }
340
0
    }
341
342
    /* -------------------------------------------------------------------- */
343
    /*      Destroy the raster bands if they exist.                         */
344
    /* -------------------------------------------------------------------- */
345
0
    for (int i = 0; i < nBands && papoBands != nullptr; ++i)
346
0
    {
347
0
        if (papoBands[i] != nullptr)
348
0
            delete papoBands[i];
349
0
        papoBands[i] = nullptr;
350
0
    }
351
352
0
    CPLFree(papoBands);
353
354
0
    if (m_poStyleTable)
355
0
    {
356
0
        delete m_poStyleTable;
357
0
        m_poStyleTable = nullptr;
358
0
    }
359
360
0
    if (m_poPrivate != nullptr)
361
0
    {
362
0
        if (m_poPrivate->hMutex != nullptr)
363
0
            CPLDestroyMutex(m_poPrivate->hMutex);
364
365
0
#if defined(__COVERITY__) || defined(DEBUG)
366
        // Not needed since at destruction there is no risk of concurrent use.
367
0
        std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
368
0
#endif
369
0
        CPLFree(m_poPrivate->m_pszWKTCached);
370
0
        if (m_poPrivate->m_poSRSCached)
371
0
        {
372
0
            m_poPrivate->m_poSRSCached->Release();
373
0
        }
374
0
        CPLFree(m_poPrivate->m_pszWKTGCPCached);
375
0
        if (m_poPrivate->m_poSRSGCPCached)
376
0
        {
377
0
            m_poPrivate->m_poSRSGCPCached->Release();
378
0
        }
379
0
    }
380
381
0
    delete m_poPrivate;
382
383
0
    CSLDestroy(papszOpenOptions);
384
0
}
385
386
/************************************************************************/
387
/*                             Close()                                  */
388
/************************************************************************/
389
390
/** Do final cleanup before a dataset is destroyed.
391
 *
392
 * This method is typically called by GDALClose() or the destructor of a
393
 * GDALDataset subclass. It might also be called by C++ users before
394
 * destroying a dataset. It should not be called on a shared dataset whose
395
 * reference count is greater than one.
396
 *
397
 * It gives a last chance to the closing process to return an error code if
398
 * something goes wrong, in particular in creation / update scenarios where
399
 * file write or network communication might occur when finalizing the dataset.
400
 *
401
 * Implementations should be robust to this method to be called several times
402
 * (on subsequent calls, it should do nothing and return CE_None).
403
 * Once it has been called, no other method than Close() or the dataset
404
 * destructor should be called. RasterBand or OGRLayer owned by the dataset
405
 * should be assumed as no longer being valid.
406
 *
407
 * If a driver implements this method, it must also call it from its
408
 * dataset destructor.
409
 *
410
 * A typical implementation might look as the following
411
 * \code{.cpp}
412
 *
413
 *  MyDataset::~MyDataset()
414
 *  {
415
 *     try
416
 *     {
417
 *         MyDataset::Close();
418
 *     }
419
 *     catch (const std::exception &exc)
420
 *     {
421
 *         // If Close() can throw exception
422
 *         CPLError(CE_Failure, CPLE_AppDefined,
423
 *                  "Exception thrown in MyDataset::Close(): %s",
424
 *                  exc.what());
425
 *     }
426
 *     catch (...)
427
 *     {
428
 *         // If Close() can throw exception
429
 *         CPLError(CE_Failure, CPLE_AppDefined,
430
 *                  "Exception thrown in MyDataset::Close()");
431
 *     }
432
 *  }
433
 *
434
 *  CPLErr MyDataset::Close()
435
 *  {
436
 *      CPLErr eErr = CE_None;
437
 *      if( nOpenFlags != OPEN_FLAGS_CLOSED )
438
 *      {
439
 *          if( MyDataset::FlushCache(true) != CE_None )
440
 *              eErr = CE_Failure;
441
 *
442
 *          // Do something driver specific
443
 *          if (m_fpImage)
444
 *          {
445
 *              if( VSIFCloseL(m_fpImage) != 0 )
446
 *              {
447
 *                  CPLError(CE_Failure, CPLE_FileIO, "VSIFCloseL() failed");
448
 *                  eErr = CE_Failure;
449
 *              }
450
 *          }
451
 *
452
 *          // Call parent Close() implementation.
453
 *          if( MyParentDatasetClass::Close() != CE_None )
454
 *              eErr = CE_Failure;
455
 *      }
456
 *      return eErr;
457
 *  }
458
 * \endcode
459
 *
460
 * @since GDAL 3.7
461
 */
462
CPLErr GDALDataset::Close()
463
0
{
464
    // Call UnregisterFromSharedDataset() before altering nOpenFlags
465
0
    UnregisterFromSharedDataset();
466
467
0
    nOpenFlags = OPEN_FLAGS_CLOSED;
468
0
    return CE_None;
469
0
}
470
471
/************************************************************************/
472
/*                UnregisterFromSharedDataset()                         */
473
/************************************************************************/
474
475
void GDALDataset::UnregisterFromSharedDataset()
476
0
{
477
0
    if (!(!bIsInternal && bShared && poAllDatasetMap && phSharedDatasetSet))
478
0
        return;
479
480
0
    CPLMutexHolderD(&hDLMutex);
481
482
0
    std::map<GDALDataset *, GIntBig>::iterator oIter =
483
0
        poAllDatasetMap->find(this);
484
0
    CPLAssert(oIter != poAllDatasetMap->end());
485
0
    const GIntBig nPIDCreatorForShared = oIter->second;
486
0
    bShared = false;
487
0
    SharedDatasetCtxt sStruct;
488
0
    sStruct.nPID = nPIDCreatorForShared;
489
0
    sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
490
0
    sStruct.pszDescription = const_cast<char *>(GetDescription());
491
0
    std::string osConcatenatedOpenOptions =
492
0
        GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
493
0
    sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
494
0
    sStruct.poDS = nullptr;
495
0
    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
496
0
        CPLHashSetLookup(phSharedDatasetSet, &sStruct));
497
0
    if (psStruct && psStruct->poDS == this)
498
0
    {
499
0
        CPLHashSetRemove(phSharedDatasetSet, psStruct);
500
0
    }
501
0
    else
502
0
    {
503
0
        CPLDebug("GDAL",
504
0
                 "Should not happen. Cannot find %s, "
505
0
                 "this=%p in phSharedDatasetSet",
506
0
                 GetDescription(), this);
507
0
    }
508
0
}
509
510
/************************************************************************/
511
/*                      AddToDatasetOpenList()                          */
512
/************************************************************************/
513
514
void GDALDataset::AddToDatasetOpenList()
515
0
{
516
    /* -------------------------------------------------------------------- */
517
    /*      Add this dataset to the open dataset list.                      */
518
    /* -------------------------------------------------------------------- */
519
0
    bIsInternal = false;
520
521
0
    CPLMutexHolderD(&hDLMutex);
522
523
0
    if (poAllDatasetMap == nullptr)
524
0
        poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
525
0
    (*poAllDatasetMap)[this] = -1;
526
0
}
527
528
/************************************************************************/
529
/*                             FlushCache()                             */
530
/************************************************************************/
531
532
/**
533
 * \brief Flush all write cached data to disk.
534
 *
535
 * Any raster (or other GDAL) data written via GDAL calls, but buffered
536
 * internally will be written to disk.
537
 *
538
 * The default implementation of this method just calls the FlushCache() method
539
 * on each of the raster bands and the SyncToDisk() method
540
 * on each of the layers.  Conceptually, calling FlushCache() on a dataset
541
 * should include any work that might be accomplished by calling SyncToDisk()
542
 * on layers in that dataset.
543
 *
544
 * Using this method does not prevent use from calling GDALClose()
545
 * to properly close a dataset and ensure that important data not addressed
546
 * by FlushCache() is written in the file.
547
 *
548
 * This method is the same as the C function GDALFlushCache().
549
 *
550
 * @param bAtClosing Whether this is called from a GDALDataset destructor
551
 * @return CE_None in case of success (note: return value added in GDAL 3.7)
552
 */
553
554
CPLErr GDALDataset::FlushCache(bool bAtClosing)
555
556
0
{
557
0
    CPLErr eErr = CE_None;
558
    // This sometimes happens if a dataset is destroyed before completely
559
    // built.
560
561
0
    if (papoBands)
562
0
    {
563
0
        for (int i = 0; i < nBands; ++i)
564
0
        {
565
0
            if (papoBands[i])
566
0
            {
567
0
                if (papoBands[i]->FlushCache(bAtClosing) != CE_None)
568
0
                    eErr = CE_Failure;
569
0
            }
570
0
        }
571
0
    }
572
573
0
    const int nLayers = GetLayerCount();
574
    // cppcheck-suppress knownConditionTrueFalse
575
0
    if (nLayers > 0)
576
0
    {
577
0
        CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
578
0
        for (int i = 0; i < nLayers; ++i)
579
0
        {
580
0
            OGRLayer *poLayer = GetLayer(i);
581
582
0
            if (poLayer)
583
0
            {
584
0
                if (poLayer->SyncToDisk() != OGRERR_NONE)
585
0
                    eErr = CE_Failure;
586
0
            }
587
0
        }
588
0
    }
589
590
0
    return eErr;
591
0
}
592
593
/************************************************************************/
594
/*                           GDALFlushCache()                           */
595
/************************************************************************/
596
597
/**
598
 * \brief Flush all write cached data to disk.
599
 *
600
 * @see GDALDataset::FlushCache().
601
 * @return CE_None in case of success (note: return value added in GDAL 3.7)
602
 */
603
604
CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS)
605
606
0
{
607
0
    VALIDATE_POINTER1(hDS, "GDALFlushCache", CE_Failure);
608
609
0
    return GDALDataset::FromHandle(hDS)->FlushCache(false);
610
0
}
611
612
/************************************************************************/
613
/*                             DropCache()                              */
614
/************************************************************************/
615
616
/**
617
* \brief Drop all write cached data
618
*
619
* This method is the same as the C function GDALDropCache().
620
*
621
* @return CE_None in case of success
622
* @since 3.9
623
*/
624
625
CPLErr GDALDataset::DropCache()
626
627
0
{
628
0
    CPLErr eErr = CE_None;
629
630
0
    if (papoBands)
631
0
    {
632
0
        for (int i = 0; i < nBands; ++i)
633
0
        {
634
0
            if (papoBands[i])
635
0
            {
636
0
                if (papoBands[i]->DropCache() != CE_None)
637
0
                    eErr = CE_Failure;
638
0
            }
639
0
        }
640
0
    }
641
642
0
    return eErr;
643
0
}
644
645
/************************************************************************/
646
/*                           GDALDropCache()                           */
647
/************************************************************************/
648
649
/**
650
* \brief Drop all write cached data
651
*
652
* @see GDALDataset::DropCache().
653
* @return CE_None in case of success
654
* @since 3.9
655
*/
656
657
CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS)
658
659
0
{
660
0
    VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure);
661
662
0
    return GDALDataset::FromHandle(hDS)->DropCache();
663
0
}
664
665
/************************************************************************/
666
/*                      GetEstimatedRAMUsage()                          */
667
/************************************************************************/
668
669
/**
670
 * \brief Return the intrinsic RAM usage of this dataset.
671
 *
672
 * The returned value should take into account caches in the underlying driver
673
 * and decoding library, but not the usage related to the GDAL block cache.
674
 *
675
 * At time of writing, this method is only implemented in the JP2OpenJPEG
676
 * driver. For single-tiled JPEG2000 images, the decoding of the image,
677
 * even partially, involves allocating at least
678
 * width * height * number_of_bands * sizeof(uint32_t) bytes inside the libopenjp2
679
 * library.
680
 *
681
 * This method is used by the GDALDatasetPool class, itself used by the GDAL VRT
682
 * driver, to determine how long a dataset in the pool must be kept open, given
683
 * the RAM usage of the dataset with respect to the usable total RAM.
684
 *
685
 * @since GDAL 3.7
686
 * @return RAM usage in bytes, or -1 if unknown (the default implementation
687
 * returns -1)
688
 */
689
690
GIntBig GDALDataset::GetEstimatedRAMUsage()
691
0
{
692
0
    return -1;
693
0
}
694
695
/************************************************************************/
696
/*                        BlockBasedFlushCache()                        */
697
/*                                                                      */
698
/*      This helper method can be called by the                         */
699
/*      GDALDataset::FlushCache() for particular drivers to ensure      */
700
/*      that buffers will be flushed in a manner suitable for pixel     */
701
/*      interleaved (by block) IO.  That is, if all the bands have      */
702
/*      the same size blocks then a given block will be flushed for     */
703
/*      all bands before proceeding to the next block.                  */
704
/************************************************************************/
705
706
//! @cond Doxygen_Suppress
707
CPLErr GDALDataset::BlockBasedFlushCache(bool bAtClosing)
708
709
0
{
710
0
    GDALRasterBand *poBand1 = GetRasterBand(1);
711
0
    if (poBand1 == nullptr || (IsMarkedSuppressOnClose() && bAtClosing))
712
0
    {
713
0
        return GDALDataset::FlushCache(bAtClosing);
714
0
    }
715
716
0
    int nBlockXSize = 0;
717
0
    int nBlockYSize = 0;
718
0
    poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
719
720
    /* -------------------------------------------------------------------- */
721
    /*      Verify that all bands match.                                    */
722
    /* -------------------------------------------------------------------- */
723
0
    for (int iBand = 1; iBand < nBands; ++iBand)
724
0
    {
725
0
        GDALRasterBand *poBand = GetRasterBand(iBand + 1);
726
727
0
        int nThisBlockXSize, nThisBlockYSize;
728
0
        poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
729
0
        if (nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize)
730
0
        {
731
0
            return GDALDataset::FlushCache(bAtClosing);
732
0
        }
733
0
    }
734
735
    /* -------------------------------------------------------------------- */
736
    /*      Now flush writable data.                                        */
737
    /* -------------------------------------------------------------------- */
738
0
    for (int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY)
739
0
    {
740
0
        for (int iX = 0; iX < poBand1->nBlocksPerRow; ++iX)
741
0
        {
742
0
            for (int iBand = 0; iBand < nBands; ++iBand)
743
0
            {
744
0
                const CPLErr eErr = papoBands[iBand]->FlushBlock(iX, iY);
745
746
0
                if (eErr != CE_None)
747
0
                    return CE_Failure;
748
0
            }
749
0
        }
750
0
    }
751
0
    return CE_None;
752
0
}
753
754
/************************************************************************/
755
/*                          RasterInitialize()                          */
756
/*                                                                      */
757
/*      Initialize raster size                                          */
758
/************************************************************************/
759
760
void GDALDataset::RasterInitialize(int nXSize, int nYSize)
761
762
0
{
763
0
    CPLAssert(nXSize > 0 && nYSize > 0);
764
765
0
    nRasterXSize = nXSize;
766
0
    nRasterYSize = nYSize;
767
0
}
768
769
//! @endcond
770
771
/************************************************************************/
772
/*                              AddBand()                               */
773
/************************************************************************/
774
775
/**
776
 * \fn GDALDataset::AddBand(GDALDataType, char**)
777
 * \brief Add a band to a dataset.
778
 *
779
 * This method will add a new band to the dataset if the underlying format
780
 * supports this action.  Most formats do not.
781
 *
782
 * Note that the new GDALRasterBand is not returned.  It may be fetched
783
 * after successful completion of the method by calling
784
 * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
785
 * band will always be the last band.
786
 *
787
 * @param eType the data type of the pixels in the new band.
788
 *
789
 * @param papszOptions a list of NAME=VALUE option strings.  The supported
790
 * options are format specific.  NULL may be passed by default.
791
 *
792
 * @return CE_None on success or CE_Failure on failure.
793
 */
794
795
CPLErr GDALDataset::AddBand(CPL_UNUSED GDALDataType eType,
796
                            CPL_UNUSED char **papszOptions)
797
798
0
{
799
0
    ReportError(CE_Failure, CPLE_NotSupported,
800
0
                "Dataset does not support the AddBand() method.");
801
802
0
    return CE_Failure;
803
0
}
804
805
/************************************************************************/
806
/*                            GDALAddBand()                             */
807
/************************************************************************/
808
809
/**
810
 * \brief Add a band to a dataset.
811
 *
812
 * @see GDALDataset::AddBand().
813
 */
814
815
CPLErr CPL_STDCALL GDALAddBand(GDALDatasetH hDataset, GDALDataType eType,
816
                               CSLConstList papszOptions)
817
818
0
{
819
0
    VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
820
821
0
    return GDALDataset::FromHandle(hDataset)->AddBand(
822
0
        eType, const_cast<char **>(papszOptions));
823
0
}
824
825
/************************************************************************/
826
/*                              SetBand()                               */
827
/************************************************************************/
828
829
//! @cond Doxygen_Suppress
830
/**  Set a band in the band array, updating the band count, and array size
831
 * appropriately.
832
 *
833
 * @param nNewBand new band number (indexing starts at 1)
834
 * @param poBand band object.
835
 */
836
837
void GDALDataset::SetBand(int nNewBand, GDALRasterBand *poBand)
838
839
0
{
840
    /* -------------------------------------------------------------------- */
841
    /*      Do we need to grow the bands list?                              */
842
    /* -------------------------------------------------------------------- */
843
0
    if (nBands < nNewBand || papoBands == nullptr)
844
0
    {
845
0
        GDALRasterBand **papoNewBands = nullptr;
846
847
0
        if (papoBands == nullptr)
848
0
            papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
849
0
                sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
850
0
        else
851
0
            papoNewBands = static_cast<GDALRasterBand **>(
852
0
                VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
853
0
                                          std::max(nNewBand, nBands)));
854
0
        if (papoNewBands == nullptr)
855
0
        {
856
0
            ReportError(CE_Failure, CPLE_OutOfMemory,
857
0
                        "Cannot allocate band array");
858
0
            return;
859
0
        }
860
861
0
        papoBands = papoNewBands;
862
863
0
        for (int i = nBands; i < nNewBand; ++i)
864
0
            papoBands[i] = nullptr;
865
866
0
        nBands = std::max(nBands, nNewBand);
867
868
0
        if (m_poPrivate)
869
0
        {
870
0
            for (int i = static_cast<int>(m_poPrivate->m_anBandMap.size());
871
0
                 i < nBands; ++i)
872
0
            {
873
0
                m_poPrivate->m_anBandMap.push_back(i + 1);
874
0
            }
875
0
        }
876
0
    }
877
878
    /* -------------------------------------------------------------------- */
879
    /*      Set the band.  Resetting the band is currently not permitted.   */
880
    /* -------------------------------------------------------------------- */
881
0
    if (papoBands[nNewBand - 1] != nullptr)
882
0
    {
883
0
        ReportError(CE_Failure, CPLE_NotSupported,
884
0
                    "Cannot set band %d as it is already set", nNewBand);
885
0
        return;
886
0
    }
887
888
0
    papoBands[nNewBand - 1] = poBand;
889
890
    /* -------------------------------------------------------------------- */
891
    /*      Set back reference information on the raster band.  Note        */
892
    /*      that the GDALDataset is a friend of the GDALRasterBand          */
893
    /*      specifically to allow this.                                     */
894
    /* -------------------------------------------------------------------- */
895
0
    poBand->nBand = nNewBand;
896
0
    poBand->poDS = this;
897
0
    poBand->nRasterXSize = nRasterXSize;
898
0
    poBand->nRasterYSize = nRasterYSize;
899
0
    poBand->eAccess = eAccess;  // Default access to be same as dataset.
900
0
}
901
902
//! @endcond
903
904
/************************************************************************/
905
/*                              SetBand()                               */
906
/************************************************************************/
907
908
//! @cond Doxygen_Suppress
909
/**  Set a band in the band array, updating the band count, and array size
910
 * appropriately.
911
 *
912
 * @param nNewBand new band number (indexing starts at 1)
913
 * @param poBand band object.
914
 */
915
916
void GDALDataset::SetBand(int nNewBand, std::unique_ptr<GDALRasterBand> poBand)
917
0
{
918
0
    SetBand(nNewBand, poBand.release());
919
0
}
920
921
//! @endcond
922
923
/************************************************************************/
924
/*                           GetRasterXSize()                           */
925
/************************************************************************/
926
927
/**
928
929
 \brief Fetch raster width in pixels.
930
931
 Equivalent of the C function GDALGetRasterXSize().
932
933
 @return the width in pixels of raster bands in this GDALDataset.
934
935
*/
936
937
int GDALDataset::GetRasterXSize() const
938
0
{
939
0
    return nRasterXSize;
940
0
}
941
942
/************************************************************************/
943
/*                         GDALGetRasterXSize()                         */
944
/************************************************************************/
945
946
/**
947
 * \brief Fetch raster width in pixels.
948
 *
949
 * @see GDALDataset::GetRasterXSize().
950
 */
951
952
int CPL_STDCALL GDALGetRasterXSize(GDALDatasetH hDataset)
953
954
0
{
955
0
    VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
956
957
0
    return GDALDataset::FromHandle(hDataset)->GetRasterXSize();
958
0
}
959
960
/************************************************************************/
961
/*                           GetRasterYSize()                           */
962
/************************************************************************/
963
964
/**
965
966
 \brief Fetch raster height in pixels.
967
968
 Equivalent of the C function GDALGetRasterYSize().
969
970
 @return the height in pixels of raster bands in this GDALDataset.
971
972
*/
973
974
int GDALDataset::GetRasterYSize() const
975
0
{
976
0
    return nRasterYSize;
977
0
}
978
979
/************************************************************************/
980
/*                         GDALGetRasterYSize()                         */
981
/************************************************************************/
982
983
/**
984
 * \brief Fetch raster height in pixels.
985
 *
986
 * @see GDALDataset::GetRasterYSize().
987
 */
988
989
int CPL_STDCALL GDALGetRasterYSize(GDALDatasetH hDataset)
990
991
0
{
992
0
    VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
993
994
0
    return GDALDataset::FromHandle(hDataset)->GetRasterYSize();
995
0
}
996
997
/************************************************************************/
998
/*                           GetRasterBand()                            */
999
/************************************************************************/
1000
1001
/**
1002
1003
 \brief Fetch a band object for a dataset.
1004
1005
 See GetBands() for a C++ iterator version of this method.
1006
1007
 Equivalent of the C function GDALGetRasterBand().
1008
1009
 @param nBandId the index number of the band to fetch, from 1 to
1010
                GetRasterCount().
1011
1012
 @return the nBandId th band object
1013
1014
*/
1015
1016
GDALRasterBand *GDALDataset::GetRasterBand(int nBandId)
1017
1018
0
{
1019
0
    if (papoBands)
1020
0
    {
1021
0
        if (nBandId < 1 || nBandId > nBands)
1022
0
        {
1023
0
            ReportError(CE_Failure, CPLE_IllegalArg,
1024
0
                        "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1025
0
                        nBandId);
1026
0
            return nullptr;
1027
0
        }
1028
1029
0
        return papoBands[nBandId - 1];
1030
0
    }
1031
0
    return nullptr;
1032
0
}
1033
1034
/************************************************************************/
1035
/*                           GetRasterBand()                            */
1036
/************************************************************************/
1037
1038
/**
1039
1040
 \brief Fetch a band object for a dataset.
1041
1042
 See GetBands() for a C++ iterator version of this method.
1043
1044
 Equivalent of the C function GDALGetRasterBand().
1045
1046
 @param nBandId the index number of the band to fetch, from 1 to
1047
                GetRasterCount().
1048
1049
 @return the nBandId th band object
1050
1051
*/
1052
1053
const GDALRasterBand *GDALDataset::GetRasterBand(int nBandId) const
1054
1055
0
{
1056
0
    if (papoBands)
1057
0
    {
1058
0
        if (nBandId < 1 || nBandId > nBands)
1059
0
        {
1060
0
            ReportError(CE_Failure, CPLE_IllegalArg,
1061
0
                        "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
1062
0
                        nBandId);
1063
0
            return nullptr;
1064
0
        }
1065
1066
0
        return papoBands[nBandId - 1];
1067
0
    }
1068
0
    return nullptr;
1069
0
}
1070
1071
/************************************************************************/
1072
/*                         GDALGetRasterBand()                          */
1073
/************************************************************************/
1074
1075
/**
1076
 * \brief Fetch a band object for a dataset.
1077
 * @see GDALDataset::GetRasterBand().
1078
 */
1079
1080
GDALRasterBandH CPL_STDCALL GDALGetRasterBand(GDALDatasetH hDS, int nBandId)
1081
1082
0
{
1083
0
    VALIDATE_POINTER1(hDS, "GDALGetRasterBand", nullptr);
1084
1085
0
    return GDALRasterBand::ToHandle(
1086
0
        GDALDataset::FromHandle(hDS)->GetRasterBand(nBandId));
1087
0
}
1088
1089
/************************************************************************/
1090
/*                           GetRasterCount()                           */
1091
/************************************************************************/
1092
1093
/**
1094
 * \brief Fetch the number of raster bands on this dataset.
1095
 *
1096
 * Same as the C function GDALGetRasterCount().
1097
 *
1098
 * @return the number of raster bands.
1099
 */
1100
1101
int GDALDataset::GetRasterCount() const
1102
0
{
1103
0
    return papoBands ? nBands : 0;
1104
0
}
1105
1106
/************************************************************************/
1107
/*                         GDALGetRasterCount()                         */
1108
/************************************************************************/
1109
1110
/**
1111
 * \brief Fetch the number of raster bands on this dataset.
1112
 *
1113
 * @see GDALDataset::GetRasterCount().
1114
 */
1115
1116
int CPL_STDCALL GDALGetRasterCount(GDALDatasetH hDS)
1117
1118
0
{
1119
0
    VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
1120
1121
0
    return GDALDataset::FromHandle(hDS)->GetRasterCount();
1122
0
}
1123
1124
/************************************************************************/
1125
/*                          GetProjectionRef()                          */
1126
/************************************************************************/
1127
1128
/**
1129
 * \brief Fetch the projection definition string for this dataset.
1130
 *
1131
 * Same as the C function GDALGetProjectionRef().
1132
 *
1133
 * The returned string defines the projection coordinate system of the
1134
 * image in OpenGIS WKT format.  It should be suitable for use with the
1135
 * OGRSpatialReference class.
1136
 *
1137
 * When a projection definition is not available an empty (but not NULL)
1138
 * string is returned.
1139
 *
1140
 * \note Starting with GDAL 3.0, this is a compatibility layer around
1141
 * GetSpatialRef()
1142
 *
1143
 * @return a pointer to an internal projection reference string.  It should
1144
 * not be altered, freed or expected to last for long.
1145
 *
1146
 * @see https://gdal.org/tutorials/osr_api_tut.html
1147
 */
1148
1149
const char *GDALDataset::GetProjectionRef() const
1150
0
{
1151
0
    const auto poSRS = GetSpatialRef();
1152
0
    if (!poSRS || !m_poPrivate)
1153
0
    {
1154
0
        return "";
1155
0
    }
1156
0
    char *pszWKT = nullptr;
1157
0
    poSRS->exportToWkt(&pszWKT);
1158
0
    if (!pszWKT)
1159
0
    {
1160
0
        return "";
1161
0
    }
1162
1163
    // If called on a thread-safe dataset, we might be called by several
1164
    // threads, so make sure our accesses to m_pszWKTCached are protected
1165
    // by a mutex.
1166
0
    std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1167
0
    if (m_poPrivate->m_pszWKTCached &&
1168
0
        strcmp(pszWKT, m_poPrivate->m_pszWKTCached) == 0)
1169
0
    {
1170
0
        CPLFree(pszWKT);
1171
0
        return m_poPrivate->m_pszWKTCached;
1172
0
    }
1173
0
    CPLFree(m_poPrivate->m_pszWKTCached);
1174
0
    m_poPrivate->m_pszWKTCached = pszWKT;
1175
0
    return m_poPrivate->m_pszWKTCached;
1176
0
}
1177
1178
/************************************************************************/
1179
/*                           GetSpatialRef()                            */
1180
/************************************************************************/
1181
1182
/**
1183
 * \brief Fetch the spatial reference for this dataset.
1184
 *
1185
 * Same as the C function GDALGetSpatialRef().
1186
 *
1187
 * When a projection definition is not available, null is returned. If used on
1188
 * a dataset where there are GCPs and not a geotransform, this method returns
1189
 * null. Use GetGCPSpatialRef() instead.
1190
 *
1191
 * @since GDAL 3.0
1192
 *
1193
 * @return a pointer to an internal object. It should not be altered or freed.
1194
 * Its lifetime will be the one of the dataset object, or until the next
1195
 * call to this method.
1196
 *
1197
 * @see https://gdal.org/tutorials/osr_api_tut.html
1198
 */
1199
1200
const OGRSpatialReference *GDALDataset::GetSpatialRef() const
1201
0
{
1202
0
    return nullptr;
1203
0
}
1204
1205
/************************************************************************/
1206
/*                        GDALGetSpatialRef()                           */
1207
/************************************************************************/
1208
1209
/**
1210
 * \brief Fetch the spatial reference for this dataset.
1211
 *
1212
 * @since GDAL 3.0
1213
 *
1214
 * @see GDALDataset::GetSpatialRef()
1215
 */
1216
1217
OGRSpatialReferenceH GDALGetSpatialRef(GDALDatasetH hDS)
1218
1219
0
{
1220
0
    VALIDATE_POINTER1(hDS, "GDALGetSpatialRef", nullptr);
1221
1222
0
    return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1223
0
        GDALDataset::FromHandle(hDS)->GetSpatialRef()));
1224
0
}
1225
1226
/************************************************************************/
1227
/*                        GDALGetProjectionRef()                        */
1228
/************************************************************************/
1229
1230
/**
1231
 * \brief Fetch the projection definition string for this dataset.
1232
 *
1233
 * @see GDALDataset::GetProjectionRef()
1234
 */
1235
1236
const char *CPL_STDCALL GDALGetProjectionRef(GDALDatasetH hDS)
1237
1238
0
{
1239
0
    VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", nullptr);
1240
1241
0
    return GDALDataset::FromHandle(hDS)->GetProjectionRef();
1242
0
}
1243
1244
/************************************************************************/
1245
/*                           SetProjection()                            */
1246
/************************************************************************/
1247
1248
/**
1249
 * \brief Set the projection reference string for this dataset.
1250
 *
1251
 * The string should be in OGC WKT or PROJ.4 format.  An error may occur
1252
 * because of incorrectly specified projection strings, because the dataset
1253
 * is not writable, or because the dataset does not support the indicated
1254
 * projection.  Many formats do not support writing projections.
1255
 *
1256
 * This method is the same as the C GDALSetProjection() function.
1257
 *
1258
 * \note Startig with GDAL 3.0, this is a compatibility layer around
1259
 * SetSpatialRef()
1260
1261
 * @param pszProjection projection reference string.
1262
 *
1263
 * @return CE_Failure if an error occurs, otherwise CE_None.
1264
 */
1265
1266
CPLErr GDALDataset::SetProjection(const char *pszProjection)
1267
0
{
1268
0
    if (pszProjection && pszProjection[0] != '\0')
1269
0
    {
1270
0
        OGRSpatialReference oSRS;
1271
0
        oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1272
0
        if (oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE)
1273
0
        {
1274
0
            return CE_Failure;
1275
0
        }
1276
0
        return SetSpatialRef(&oSRS);
1277
0
    }
1278
0
    else
1279
0
    {
1280
0
        return SetSpatialRef(nullptr);
1281
0
    }
1282
0
}
1283
1284
/************************************************************************/
1285
/*                           SetSpatialRef()                            */
1286
/************************************************************************/
1287
1288
/**
1289
 * \brief Set the spatial reference system for this dataset.
1290
 *
1291
 * An error may occur because the dataset
1292
 * is not writable, or because the dataset does not support the indicated
1293
 * projection. Many formats do not support writing projections.
1294
 *
1295
 * This method is the same as the C GDALSetSpatialRef() function.
1296
 *
1297
 * @since GDAL 3.0
1298
1299
 * @param poSRS spatial reference system object. nullptr can potentially be
1300
 * passed for drivers that support unsetting the SRS.
1301
 *
1302
 * @return CE_Failure if an error occurs, otherwise CE_None.
1303
 */
1304
1305
CPLErr GDALDataset::SetSpatialRef(CPL_UNUSED const OGRSpatialReference *poSRS)
1306
0
{
1307
0
    if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1308
0
        ReportError(CE_Failure, CPLE_NotSupported,
1309
0
                    "Dataset does not support the SetSpatialRef() method.");
1310
0
    return CE_Failure;
1311
0
}
1312
1313
/************************************************************************/
1314
/*                         GDALSetSpatialRef()                          */
1315
/************************************************************************/
1316
1317
/**
1318
 * \brief Set the spatial reference system for this dataset.
1319
 *
1320
 * @since GDAL 3.0
1321
 *
1322
 * @see GDALDataset::SetSpatialRef()
1323
 */
1324
1325
CPLErr GDALSetSpatialRef(GDALDatasetH hDS, OGRSpatialReferenceH hSRS)
1326
1327
0
{
1328
0
    VALIDATE_POINTER1(hDS, "GDALSetSpatialRef", CE_Failure);
1329
1330
0
    return GDALDataset::FromHandle(hDS)->SetSpatialRef(
1331
0
        OGRSpatialReference::FromHandle(hSRS));
1332
0
}
1333
1334
/************************************************************************/
1335
/*                         GDALSetProjection()                          */
1336
/************************************************************************/
1337
1338
/**
1339
 * \brief Set the projection reference string for this dataset.
1340
 *
1341
 * @see GDALDataset::SetProjection()
1342
 */
1343
1344
CPLErr CPL_STDCALL GDALSetProjection(GDALDatasetH hDS,
1345
                                     const char *pszProjection)
1346
1347
0
{
1348
0
    VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
1349
1350
0
    return GDALDataset::FromHandle(hDS)->SetProjection(pszProjection);
1351
0
}
1352
1353
/************************************************************************/
1354
/*                          GetGeoTransform()                           */
1355
/************************************************************************/
1356
1357
/**
1358
 * \brief Fetch the affine transformation coefficients.
1359
 *
1360
 * Fetches the coefficients for transforming between pixel/line (P,L) raster
1361
 * space, and projection coordinates (Xp,Yp) space.
1362
 *
1363
 * \code
1364
 *   Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
1365
 *   Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
1366
 * \endcode
1367
 *
1368
 * In a north up image, padfTransform[1] is the pixel width, and
1369
 * padfTransform[5] is the pixel height.  The upper left corner of the
1370
 * upper left pixel is at position (padfTransform[0],padfTransform[3]).
1371
 *
1372
 * The default transform is (0,1,0,0,0,1) and should be returned even when
1373
 * a CE_Failure error is returned, such as for formats that don't support
1374
 * transformation to projection coordinates.
1375
 *
1376
 * This method does the same thing as the C GDALGetGeoTransform() function.
1377
 *
1378
 * @param padfTransform an existing six double buffer into which the
1379
 * transformation will be placed.
1380
 *
1381
 * @return CE_None on success, or CE_Failure if no transform can be fetched.
1382
 */
1383
1384
CPLErr GDALDataset::GetGeoTransform(double *padfTransform)
1385
1386
0
{
1387
0
    CPLAssert(padfTransform != nullptr);
1388
1389
0
    padfTransform[0] = 0.0;  // X Origin (top left corner)
1390
0
    padfTransform[1] = 1.0;  // X Pixel size */
1391
0
    padfTransform[2] = 0.0;
1392
1393
0
    padfTransform[3] = 0.0;  // Y Origin (top left corner)
1394
0
    padfTransform[4] = 0.0;
1395
0
    padfTransform[5] = 1.0;  // Y Pixel Size
1396
1397
0
    return CE_Failure;
1398
0
}
1399
1400
/************************************************************************/
1401
/*                        GDALGetGeoTransform()                         */
1402
/************************************************************************/
1403
1404
/**
1405
 * \brief Fetch the affine transformation coefficients.
1406
 *
1407
 * @see GDALDataset::GetGeoTransform()
1408
 */
1409
1410
CPLErr CPL_STDCALL GDALGetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1411
1412
0
{
1413
0
    VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
1414
1415
0
    return GDALDataset::FromHandle(hDS)->GetGeoTransform(padfTransform);
1416
0
}
1417
1418
/************************************************************************/
1419
/*                          SetGeoTransform()                           */
1420
/************************************************************************/
1421
1422
/**
1423
 * \fn GDALDataset::SetGeoTransform(double*)
1424
 * \brief Set the affine transformation coefficients.
1425
 *
1426
 * See GetGeoTransform() for details on the meaning of the padfTransform
1427
 * coefficients.
1428
 *
1429
 * This method does the same thing as the C GDALSetGeoTransform() function.
1430
 *
1431
 * @param padfTransform a six double buffer containing the transformation
1432
 * coefficients to be written with the dataset.
1433
 *
1434
 * @return CE_None on success, or CE_Failure if this transform cannot be
1435
 * written.
1436
 */
1437
1438
CPLErr GDALDataset::SetGeoTransform(CPL_UNUSED double *padfTransform)
1439
1440
0
{
1441
0
    if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
1442
0
        ReportError(CE_Failure, CPLE_NotSupported,
1443
0
                    "SetGeoTransform() not supported for this dataset.");
1444
1445
0
    return CE_Failure;
1446
0
}
1447
1448
/************************************************************************/
1449
/*                        GDALSetGeoTransform()                         */
1450
/************************************************************************/
1451
1452
/**
1453
 * \brief Set the affine transformation coefficients.
1454
 *
1455
 * @see GDALDataset::SetGeoTransform()
1456
 */
1457
1458
CPLErr CPL_STDCALL GDALSetGeoTransform(GDALDatasetH hDS, double *padfTransform)
1459
1460
0
{
1461
0
    VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
1462
1463
0
    return GDALDataset::FromHandle(hDS)->SetGeoTransform(padfTransform);
1464
0
}
1465
1466
/************************************************************************/
1467
/*                         GetInternalHandle()                          */
1468
/************************************************************************/
1469
1470
/**
1471
 * \fn GDALDataset::GetInternalHandle(const char*)
1472
 * \brief Fetch a format specific internally meaningful handle.
1473
 *
1474
 * This method is the same as the C GDALGetInternalHandle() method.
1475
 *
1476
 * @param pszHandleName the handle name desired.  The meaningful names
1477
 * will be specific to the file format.
1478
 *
1479
 * @return the desired handle value, or NULL if not recognized/supported.
1480
 */
1481
1482
void *GDALDataset::GetInternalHandle(CPL_UNUSED const char *pszHandleName)
1483
1484
0
{
1485
0
    return nullptr;
1486
0
}
1487
1488
/************************************************************************/
1489
/*                       GDALGetInternalHandle()                        */
1490
/************************************************************************/
1491
1492
/**
1493
 * \brief Fetch a format specific internally meaningful handle.
1494
 *
1495
 * @see GDALDataset::GetInternalHandle()
1496
 */
1497
1498
void *CPL_STDCALL GDALGetInternalHandle(GDALDatasetH hDS,
1499
                                        const char *pszRequest)
1500
1501
0
{
1502
0
    VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", nullptr);
1503
1504
0
    return GDALDataset::FromHandle(hDS)->GetInternalHandle(pszRequest);
1505
0
}
1506
1507
/************************************************************************/
1508
/*                             GetDriver()                              */
1509
/************************************************************************/
1510
1511
/**
1512
 * \brief Fetch the driver to which this dataset relates.
1513
 *
1514
 * This method is the same as the C GDALGetDatasetDriver() function.
1515
 *
1516
 * @return the driver on which the dataset was created with GDALOpen() or
1517
 * GDALCreate().
1518
 */
1519
1520
GDALDriver *GDALDataset::GetDriver()
1521
0
{
1522
0
    return poDriver;
1523
0
}
1524
1525
/************************************************************************/
1526
/*                        GDALGetDatasetDriver()                        */
1527
/************************************************************************/
1528
1529
/**
1530
 * \brief Fetch the driver to which this dataset relates.
1531
 *
1532
 * @see GDALDataset::GetDriver()
1533
 */
1534
1535
GDALDriverH CPL_STDCALL GDALGetDatasetDriver(GDALDatasetH hDataset)
1536
1537
0
{
1538
0
    VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", nullptr);
1539
1540
0
    return static_cast<GDALDriverH>(
1541
0
        GDALDataset::FromHandle(hDataset)->GetDriver());
1542
0
}
1543
1544
/************************************************************************/
1545
/*                             Reference()                              */
1546
/************************************************************************/
1547
1548
/**
1549
 * \brief Add one to dataset reference count.
1550
 *
1551
 * The reference is one after instantiation.
1552
 *
1553
 * This method is the same as the C GDALReferenceDataset() function.
1554
 *
1555
 * @return the post-increment reference count.
1556
 */
1557
1558
int GDALDataset::Reference()
1559
0
{
1560
0
    return ++nRefCount;
1561
0
}
1562
1563
/************************************************************************/
1564
/*                        GDALReferenceDataset()                        */
1565
/************************************************************************/
1566
1567
/**
1568
 * \brief Add one to dataset reference count.
1569
 *
1570
 * @see GDALDataset::Reference()
1571
 */
1572
1573
int CPL_STDCALL GDALReferenceDataset(GDALDatasetH hDataset)
1574
1575
0
{
1576
0
    VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
1577
1578
0
    return GDALDataset::FromHandle(hDataset)->Reference();
1579
0
}
1580
1581
/************************************************************************/
1582
/*                            Dereference()                             */
1583
/************************************************************************/
1584
1585
/**
1586
 * \brief Subtract one from dataset reference count.
1587
 *
1588
 * The reference is one after instantiation.  Generally when the reference
1589
 * count has dropped to zero the dataset may be safely deleted (closed).
1590
 *
1591
 * This method is the same as the C GDALDereferenceDataset() function.
1592
 *
1593
 * @return the post-decrement reference count.
1594
 */
1595
1596
int GDALDataset::Dereference()
1597
0
{
1598
0
    return --nRefCount;
1599
0
}
1600
1601
/************************************************************************/
1602
/*                       GDALDereferenceDataset()                       */
1603
/************************************************************************/
1604
1605
/**
1606
 * \brief Subtract one from dataset reference count.
1607
 *
1608
 * @see GDALDataset::Dereference()
1609
 */
1610
1611
int CPL_STDCALL GDALDereferenceDataset(GDALDatasetH hDataset)
1612
1613
0
{
1614
0
    VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
1615
1616
0
    return GDALDataset::FromHandle(hDataset)->Dereference();
1617
0
}
1618
1619
/************************************************************************/
1620
/*                            ReleaseRef()                              */
1621
/************************************************************************/
1622
1623
/**
1624
 * \brief Drop a reference to this object, and destroy if no longer referenced.
1625
 * @return TRUE if the object has been destroyed.
1626
 * @since GDAL 2.2
1627
 */
1628
1629
int GDALDataset::ReleaseRef()
1630
1631
0
{
1632
0
    if (Dereference() <= 0)
1633
0
    {
1634
0
        nRefCount = 1;
1635
0
        delete this;
1636
0
        return TRUE;
1637
0
    }
1638
0
    return FALSE;
1639
0
}
1640
1641
/************************************************************************/
1642
/*                        GDALReleaseDataset()                          */
1643
/************************************************************************/
1644
1645
/**
1646
 * \brief Drop a reference to this object, and destroy if no longer referenced.
1647
 *
1648
 * @see GDALDataset::ReleaseRef()
1649
 * @since GDAL 2.2
1650
 */
1651
1652
int CPL_STDCALL GDALReleaseDataset(GDALDatasetH hDataset)
1653
1654
0
{
1655
0
    VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
1656
1657
0
    return GDALDataset::FromHandle(hDataset)->ReleaseRef();
1658
0
}
1659
1660
/************************************************************************/
1661
/*                             GetShared()                              */
1662
/************************************************************************/
1663
1664
/**
1665
 * \brief Returns shared flag.
1666
 *
1667
 * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1668
 */
1669
1670
int GDALDataset::GetShared() const
1671
0
{
1672
0
    return bShared;
1673
0
}
1674
1675
/************************************************************************/
1676
/*                            MarkAsShared()                            */
1677
/************************************************************************/
1678
1679
/**
1680
 * \brief Mark this dataset as available for sharing.
1681
 */
1682
1683
void GDALDataset::MarkAsShared()
1684
1685
0
{
1686
0
    CPLAssert(!bShared);
1687
1688
0
    bShared = true;
1689
0
    if (bIsInternal)
1690
0
        return;
1691
1692
0
    GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1693
1694
    // Insert the dataset in the set of shared opened datasets.
1695
0
    CPLMutexHolderD(&hDLMutex);
1696
0
    if (phSharedDatasetSet == nullptr)
1697
0
        phSharedDatasetSet =
1698
0
            CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
1699
0
                          GDALSharedDatasetFreeFunc);
1700
1701
0
    SharedDatasetCtxt *psStruct =
1702
0
        static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
1703
0
    psStruct->poDS = this;
1704
0
    psStruct->nPID = nPID;
1705
0
    psStruct->nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
1706
0
    psStruct->pszDescription = CPLStrdup(GetDescription());
1707
0
    std::string osConcatenatedOpenOptions =
1708
0
        GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
1709
0
    psStruct->pszConcatenatedOpenOptions =
1710
0
        CPLStrdup(osConcatenatedOpenOptions.c_str());
1711
0
    if (CPLHashSetLookup(phSharedDatasetSet, psStruct) != nullptr)
1712
0
    {
1713
0
        GDALSharedDatasetFreeFunc(psStruct);
1714
0
        ReportError(CE_Failure, CPLE_AppDefined,
1715
0
                    "An existing shared dataset already has this description. "
1716
0
                    "This should not happen.");
1717
0
    }
1718
0
    else
1719
0
    {
1720
0
        CPLHashSetInsert(phSharedDatasetSet, psStruct);
1721
1722
0
        (*poAllDatasetMap)[this] = nPID;
1723
0
    }
1724
0
}
1725
1726
/************************************************************************/
1727
/*                        MarkSuppressOnClose()                         */
1728
/************************************************************************/
1729
1730
/** Set that the dataset must be deleted on close. */
1731
void GDALDataset::MarkSuppressOnClose()
1732
0
{
1733
0
    bSuppressOnClose = true;
1734
0
}
1735
1736
/************************************************************************/
1737
/*                       UnMarkSuppressOnClose()                        */
1738
/************************************************************************/
1739
1740
/** Remove the flag requesting the dataset to be deleted on close. */
1741
void GDALDataset::UnMarkSuppressOnClose()
1742
0
{
1743
0
    bSuppressOnClose = false;
1744
0
}
1745
1746
/************************************************************************/
1747
/*                        CleanupPostFileClosing()                      */
1748
/************************************************************************/
1749
1750
/** This method should be called by driver implementations in their destructor,
1751
 * after having closed all files, but before having freed resources that
1752
 * are needed for their GetFileList() implementation.
1753
 * This is used to implement MarkSuppressOnClose behavior.
1754
 */
1755
void GDALDataset::CleanupPostFileClosing()
1756
0
{
1757
0
    if (IsMarkedSuppressOnClose())
1758
0
    {
1759
0
        char **papszFileList = GetFileList();
1760
0
        for (int i = 0; papszFileList && papszFileList[i]; ++i)
1761
0
            VSIUnlink(papszFileList[i]);
1762
0
        CSLDestroy(papszFileList);
1763
0
    }
1764
0
}
1765
1766
/************************************************************************/
1767
/*                            GetGCPCount()                             */
1768
/************************************************************************/
1769
1770
/**
1771
 * \brief Get number of GCPs.
1772
 *
1773
 * This method is the same as the C function GDALGetGCPCount().
1774
 *
1775
 * @return number of GCPs for this dataset.  Zero if there are none.
1776
 */
1777
1778
int GDALDataset::GetGCPCount()
1779
0
{
1780
0
    return 0;
1781
0
}
1782
1783
/************************************************************************/
1784
/*                          GDALGetGCPCount()                           */
1785
/************************************************************************/
1786
1787
/**
1788
 * \brief Get number of GCPs.
1789
 *
1790
 * @see GDALDataset::GetGCPCount()
1791
 */
1792
1793
int CPL_STDCALL GDALGetGCPCount(GDALDatasetH hDS)
1794
1795
0
{
1796
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
1797
1798
0
    return GDALDataset::FromHandle(hDS)->GetGCPCount();
1799
0
}
1800
1801
/************************************************************************/
1802
/*                          GetGCPProjection()                          */
1803
/************************************************************************/
1804
1805
/**
1806
 * \brief Get output projection for GCPs.
1807
 *
1808
 * This method is the same as the C function GDALGetGCPProjection().
1809
 *
1810
 * The projection string follows the normal rules from GetProjectionRef().
1811
 *
1812
 * \note Starting with GDAL 3.0, this is a compatibility layer around
1813
 * GetGCPSpatialRef()
1814
 *
1815
 * @return internal projection string or "" if there are no GCPs.
1816
 *  It should not be altered, freed or expected to last for long.
1817
 */
1818
1819
const char *GDALDataset::GetGCPProjection()
1820
0
{
1821
0
    const auto poSRS = GetGCPSpatialRef();
1822
0
    if (!poSRS || !m_poPrivate)
1823
0
    {
1824
0
        return "";
1825
0
    }
1826
0
    char *pszWKT = nullptr;
1827
0
    poSRS->exportToWkt(&pszWKT);
1828
0
    if (!pszWKT)
1829
0
    {
1830
0
        return "";
1831
0
    }
1832
1833
    // If called on a thread-safe dataset, we might be called by several
1834
    // threads, so make sure our accesses to m_pszWKTCached are protected
1835
    // by a mutex.
1836
0
    std::lock_guard oLock(m_poPrivate->m_oMutexWKT);
1837
0
    if (m_poPrivate->m_pszWKTGCPCached &&
1838
0
        strcmp(pszWKT, m_poPrivate->m_pszWKTGCPCached) == 0)
1839
0
    {
1840
0
        CPLFree(pszWKT);
1841
0
        return m_poPrivate->m_pszWKTGCPCached;
1842
0
    }
1843
0
    CPLFree(m_poPrivate->m_pszWKTGCPCached);
1844
0
    m_poPrivate->m_pszWKTGCPCached = pszWKT;
1845
0
    return m_poPrivate->m_pszWKTGCPCached;
1846
0
}
1847
1848
/************************************************************************/
1849
/*                          GetGCPSpatialRef()                          */
1850
/************************************************************************/
1851
1852
/**
1853
 * \brief Get output spatial reference system for GCPs.
1854
 *
1855
 * Same as the C function GDALGetGCPSpatialRef().
1856
 *
1857
 * When a SRS is not available, null is returned. If used on
1858
 * a dataset where there is a geotransform, and not GCPs, this method returns
1859
 * null. Use GetSpatialRef() instead.
1860
 *
1861
 * @since GDAL 3.0
1862
 *
1863
 * @return a pointer to an internal object. It should not be altered or freed.
1864
 * Its lifetime will be the one of the dataset object, or until the next
1865
 * call to this method.
1866
 */
1867
1868
const OGRSpatialReference *GDALDataset::GetGCPSpatialRef() const
1869
0
{
1870
0
    return nullptr;
1871
0
}
1872
1873
/************************************************************************/
1874
/*                       GDALGetGCPSpatialRef()                         */
1875
/************************************************************************/
1876
1877
/**
1878
 * \brief Get output spatial reference system for GCPs.
1879
 *
1880
 * @since GDAL 3.0
1881
 *
1882
 * @see GDALDataset::GetGCPSpatialRef()
1883
 */
1884
1885
OGRSpatialReferenceH GDALGetGCPSpatialRef(GDALDatasetH hDS)
1886
1887
0
{
1888
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPSpatialRef", nullptr);
1889
1890
0
    return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
1891
0
        GDALDataset::FromHandle(hDS)->GetGCPSpatialRef()));
1892
0
}
1893
1894
/************************************************************************/
1895
/*                        GDALGetGCPProjection()                        */
1896
/************************************************************************/
1897
1898
/**
1899
 * \brief Get output projection for GCPs.
1900
 *
1901
 * @see GDALDataset::GetGCPProjection()
1902
 */
1903
1904
const char *CPL_STDCALL GDALGetGCPProjection(GDALDatasetH hDS)
1905
1906
0
{
1907
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", nullptr);
1908
1909
0
    return GDALDataset::FromHandle(hDS)->GetGCPProjection();
1910
0
}
1911
1912
/************************************************************************/
1913
/*                               GetGCPs()                              */
1914
/************************************************************************/
1915
1916
/**
1917
 * \brief Fetch GCPs.
1918
 *
1919
 * This method is the same as the C function GDALGetGCPs().
1920
 *
1921
 * @return pointer to internal GCP structure list.  It should not be modified,
1922
 * and may change on the next GDAL call.
1923
 */
1924
1925
const GDAL_GCP *GDALDataset::GetGCPs()
1926
0
{
1927
0
    return nullptr;
1928
0
}
1929
1930
/************************************************************************/
1931
/*                            GDALGetGCPs()                             */
1932
/************************************************************************/
1933
1934
/**
1935
 * \brief Fetch GCPs.
1936
 *
1937
 * @see GDALDataset::GetGCPs()
1938
 */
1939
1940
const GDAL_GCP *CPL_STDCALL GDALGetGCPs(GDALDatasetH hDS)
1941
1942
0
{
1943
0
    VALIDATE_POINTER1(hDS, "GDALGetGCPs", nullptr);
1944
1945
0
    return GDALDataset::FromHandle(hDS)->GetGCPs();
1946
0
}
1947
1948
/************************************************************************/
1949
/*                              SetGCPs()                               */
1950
/************************************************************************/
1951
1952
/**
1953
 * \brief Assign GCPs.
1954
 *
1955
 * This method is the same as the C function GDALSetGCPs().
1956
 *
1957
 * This method assigns the passed set of GCPs to this dataset, as well as
1958
 * setting their coordinate system.  Internally copies are made of the
1959
 * coordinate system and list of points, so the caller remains responsible for
1960
 * deallocating these arguments if appropriate.
1961
 *
1962
 * Most formats do not support setting of GCPs, even formats that can
1963
 * handle GCPs.  These formats will return CE_Failure.
1964
 *
1965
 * \note Startig with GDAL 3.0, this is a compatibility layer around
1966
 * SetGCPs(int, const GDAL_GCP*, const char*)
1967
 *
1968
 * @param nGCPCount number of GCPs being assigned.
1969
 *
1970
 * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1971
 *
1972
 * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
1973
 * GCP output coordinates.  This parameter should be "" if no output coordinate
1974
 * system is known.
1975
 *
1976
 * @return CE_None on success, CE_Failure on failure (including if action is
1977
 * not supported for this format).
1978
 */
1979
1980
CPLErr GDALDataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList,
1981
                            const char *pszGCPProjection)
1982
1983
0
{
1984
0
    if (pszGCPProjection && pszGCPProjection[0] != '\0')
1985
0
    {
1986
0
        OGRSpatialReference oSRS;
1987
0
        oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1988
0
        if (oSRS.importFromWkt(pszGCPProjection) != OGRERR_NONE)
1989
0
        {
1990
0
            return CE_Failure;
1991
0
        }
1992
0
        return SetGCPs(nGCPCount, pasGCPList, &oSRS);
1993
0
    }
1994
0
    else
1995
0
    {
1996
0
        return SetGCPs(nGCPCount, pasGCPList,
1997
0
                       static_cast<const OGRSpatialReference *>(nullptr));
1998
0
    }
1999
0
}
2000
2001
/************************************************************************/
2002
/*                              SetGCPs()                               */
2003
/************************************************************************/
2004
2005
/**
2006
 * \brief Assign GCPs.
2007
 *
2008
 * This method is the same as the C function GDALSetGCPs().
2009
 *
2010
 * This method assigns the passed set of GCPs to this dataset, as well as
2011
 * setting their coordinate system.  Internally copies are made of the
2012
 * coordinate system and list of points, so the caller remains responsible for
2013
 * deallocating these arguments if appropriate.
2014
 *
2015
 * Most formats do not support setting of GCPs, even formats that can
2016
 * handle GCPs.  These formats will return CE_Failure.
2017
 *
2018
 * @since GDAL 3.0
2019
 *
2020
 * @param nGCPCount number of GCPs being assigned.
2021
 *
2022
 * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
2023
 *
2024
 * @param poGCP_SRS the new coordinate reference system to assign for the
2025
 * GCP output coordinates.  This parameter should be null if no output
2026
 * coordinate system is known.
2027
 *
2028
 * @return CE_None on success, CE_Failure on failure (including if action is
2029
 * not supported for this format).
2030
 */
2031
2032
CPLErr GDALDataset::SetGCPs(CPL_UNUSED int nGCPCount,
2033
                            CPL_UNUSED const GDAL_GCP *pasGCPList,
2034
                            CPL_UNUSED const OGRSpatialReference *poGCP_SRS)
2035
2036
0
{
2037
0
    if (!(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED))
2038
0
        ReportError(CE_Failure, CPLE_NotSupported,
2039
0
                    "Dataset does not support the SetGCPs() method.");
2040
2041
0
    return CE_Failure;
2042
0
}
2043
2044
/************************************************************************/
2045
/*                            GDALSetGCPs()                             */
2046
/************************************************************************/
2047
2048
/**
2049
 * \brief Assign GCPs.
2050
 *
2051
 * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
2052
 */
2053
2054
CPLErr CPL_STDCALL GDALSetGCPs(GDALDatasetH hDS, int nGCPCount,
2055
                               const GDAL_GCP *pasGCPList,
2056
                               const char *pszGCPProjection)
2057
2058
0
{
2059
0
    VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
2060
2061
0
    return GDALDataset::FromHandle(hDS)->SetGCPs(nGCPCount, pasGCPList,
2062
0
                                                 pszGCPProjection);
2063
0
}
2064
2065
/************************************************************************/
2066
/*                           GDALSetGCPs2()                             */
2067
/************************************************************************/
2068
2069
/**
2070
 * \brief Assign GCPs.
2071
 *
2072
 * @since GDAL 3.0
2073
 * @see GDALDataset::SetGCPs(int, const GDAL_GCP*, const OGRSpatialReference*)
2074
 */
2075
2076
CPLErr GDALSetGCPs2(GDALDatasetH hDS, int nGCPCount, const GDAL_GCP *pasGCPList,
2077
                    OGRSpatialReferenceH hSRS)
2078
2079
0
{
2080
0
    VALIDATE_POINTER1(hDS, "GDALSetGCPs2", CE_Failure);
2081
2082
0
    return GDALDataset::FromHandle(hDS)->SetGCPs(
2083
0
        nGCPCount, pasGCPList, OGRSpatialReference::FromHandle(hSRS));
2084
0
}
2085
2086
/************************************************************************/
2087
/*                           BuildOverviews()                           */
2088
/************************************************************************/
2089
2090
/**
2091
 * \brief Build raster overview(s)
2092
 *
2093
 * If the operation is unsupported for the indicated dataset, then
2094
 * CE_Failure is returned, and CPLGetLastErrorNo() will return
2095
 * CPLE_NotSupported.
2096
 *
2097
 * Depending on the actual file format, all overviews level can be also
2098
 * deleted by specifying nOverviews == 0. This works at least for external
2099
 * overviews (.ovr), TIFF internal overviews, etc.
2100
 *
2101
 * Starting with GDAL 3.2, the GDAL_NUM_THREADS configuration option can be set
2102
 * to "ALL_CPUS" or a integer value to specify the number of threads to use for
2103
 * overview computation.
2104
 *
2105
 * This method is the same as the C function GDALBuildOverviewsEx().
2106
 *
2107
 * @param pszResampling one of "AVERAGE", "AVERAGE_MAGPHASE", "RMS",
2108
 * "BILINEAR", "CUBIC", "CUBICSPLINE", "GAUSS", "LANCZOS", "MODE", "NEAREST",
2109
 * or "NONE" controlling the downsampling method applied.
2110
 * @param nOverviews number of overviews to build, or 0 to clean overviews.
2111
 * @param panOverviewList the list of overview decimation factors (positive
2112
 *                        integers, normally larger or equal to 2) to build, or
2113
 *                        NULL if nOverviews == 0.
2114
 * @param nListBands number of bands to build overviews for in panBandList.
2115
 * Build for all bands if this is 0.
2116
 * @param panBandList list of band numbers.
2117
 * @param pfnProgress a function to call to report progress, or NULL.
2118
 * @param pProgressData application data to pass to the progress function.
2119
 * @param papszOptions (GDAL >= 3.6) NULL terminated list of options as
2120
 *                     key=value pairs, or NULL
2121
 *
2122
 * @return CE_None on success or CE_Failure if the operation doesn't work.
2123
 *
2124
 * For example, to build overview level 2, 4 and 8 on all bands the following
2125
 * call could be made:
2126
 * \code{.cpp}
2127
 *   int       anOverviewList[3] = { 2, 4, 8 };
2128
 *
2129
 *   poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, nullptr,
2130
 *                              GDALDummyProgress, nullptr );
2131
 * \endcode
2132
 *
2133
 * @see GDALRegenerateOverviewsEx()
2134
 */
2135
2136
CPLErr GDALDataset::BuildOverviews(const char *pszResampling, int nOverviews,
2137
                                   const int *panOverviewList, int nListBands,
2138
                                   const int *panBandList,
2139
                                   GDALProgressFunc pfnProgress,
2140
                                   void *pProgressData,
2141
                                   CSLConstList papszOptions)
2142
0
{
2143
0
    int *panAllBandList = nullptr;
2144
2145
0
    if (nListBands == 0)
2146
0
    {
2147
0
        nListBands = GetRasterCount();
2148
0
        panAllBandList =
2149
0
            static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
2150
0
        for (int i = 0; i < nListBands; ++i)
2151
0
            panAllBandList[i] = i + 1;
2152
2153
0
        panBandList = panAllBandList;
2154
0
    }
2155
2156
0
    if (pfnProgress == nullptr)
2157
0
        pfnProgress = GDALDummyProgress;
2158
2159
0
    for (int i = 0; i < nOverviews; ++i)
2160
0
    {
2161
0
        if (panOverviewList[i] <= 0)
2162
0
        {
2163
0
            CPLError(CE_Failure, CPLE_IllegalArg,
2164
0
                     "panOverviewList[%d] = %d is invalid. It must be a "
2165
0
                     "positive value",
2166
0
                     i, panOverviewList[i]);
2167
0
            CPLFree(panAllBandList);
2168
0
            return CE_Failure;
2169
0
        }
2170
0
    }
2171
2172
    // At time of writing, all overview generation options are actually
2173
    // expected to be passed as configuration options.
2174
0
    std::vector<std::unique_ptr<CPLConfigOptionSetter>> apoConfigOptionSetter;
2175
0
    for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(papszOptions))
2176
0
    {
2177
0
        apoConfigOptionSetter.emplace_back(
2178
0
            std::make_unique<CPLConfigOptionSetter>(pszKey, pszValue, false));
2179
0
    }
2180
2181
0
    const CPLErr eErr =
2182
0
        IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
2183
0
                        panBandList, pfnProgress, pProgressData, papszOptions);
2184
2185
0
    if (panAllBandList != nullptr)
2186
0
        CPLFree(panAllBandList);
2187
2188
0
    return eErr;
2189
0
}
2190
2191
/************************************************************************/
2192
/*                         GDALBuildOverviews()                         */
2193
/************************************************************************/
2194
2195
/**
2196
 * \brief Build raster overview(s)
2197
 *
2198
 * @see GDALDataset::BuildOverviews() and GDALBuildOverviews()
2199
 */
2200
2201
CPLErr CPL_STDCALL GDALBuildOverviews(GDALDatasetH hDataset,
2202
                                      const char *pszResampling, int nOverviews,
2203
                                      const int *panOverviewList,
2204
                                      int nListBands, const int *panBandList,
2205
                                      GDALProgressFunc pfnProgress,
2206
                                      void *pProgressData)
2207
2208
0
{
2209
0
    VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2210
2211
0
    return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2212
0
        pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2213
0
        pfnProgress, pProgressData, nullptr);
2214
0
}
2215
2216
/************************************************************************/
2217
/*                         GDALBuildOverviews()                         */
2218
/************************************************************************/
2219
2220
/**
2221
 * \brief Build raster overview(s)
2222
 *
2223
 * @see GDALDataset::BuildOverviews()
2224
 * @since GDAL 3.6
2225
 */
2226
2227
CPLErr CPL_STDCALL
2228
GDALBuildOverviewsEx(GDALDatasetH hDataset, const char *pszResampling,
2229
                     int nOverviews, const int *panOverviewList, int nListBands,
2230
                     const int *panBandList, GDALProgressFunc pfnProgress,
2231
                     void *pProgressData, CSLConstList papszOptions)
2232
2233
0
{
2234
0
    VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
2235
2236
0
    return GDALDataset::FromHandle(hDataset)->BuildOverviews(
2237
0
        pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
2238
0
        pfnProgress, pProgressData, papszOptions);
2239
0
}
2240
2241
/************************************************************************/
2242
/*                          IBuildOverviews()                           */
2243
/*                                                                      */
2244
/*      Default implementation.                                         */
2245
/************************************************************************/
2246
2247
//! @cond Doxygen_Suppress
2248
CPLErr GDALDataset::IBuildOverviews(const char *pszResampling, int nOverviews,
2249
                                    const int *panOverviewList, int nListBands,
2250
                                    const int *panBandList,
2251
                                    GDALProgressFunc pfnProgress,
2252
                                    void *pProgressData,
2253
                                    CSLConstList papszOptions)
2254
2255
0
{
2256
0
    if (oOvManager.IsInitialized())
2257
0
        return oOvManager.BuildOverviews(
2258
0
            nullptr, pszResampling, nOverviews, panOverviewList, nListBands,
2259
0
            panBandList, pfnProgress, pProgressData, papszOptions);
2260
0
    else
2261
0
    {
2262
0
        ReportError(CE_Failure, CPLE_NotSupported,
2263
0
                    "BuildOverviews() not supported for this dataset.");
2264
2265
0
        return CE_Failure;
2266
0
    }
2267
0
}
2268
2269
//! @endcond
2270
2271
/************************************************************************/
2272
/*                             IRasterIO()                              */
2273
/*                                                                      */
2274
/*      The default implementation of IRasterIO() is, in the general    */
2275
/*      case to pass the request off to each band objects rasterio      */
2276
/*      methods with appropriate arguments. In some cases, it might     */
2277
/*      choose instead the BlockBasedRasterIO() implementation.         */
2278
/************************************************************************/
2279
2280
//! @cond Doxygen_Suppress
2281
CPLErr GDALDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2282
                              int nXSize, int nYSize, void *pData,
2283
                              int nBufXSize, int nBufYSize,
2284
                              GDALDataType eBufType, int nBandCount,
2285
                              BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
2286
                              GSpacing nLineSpace, GSpacing nBandSpace,
2287
                              GDALRasterIOExtraArg *psExtraArg)
2288
2289
0
{
2290
0
    const char *pszInterleave = nullptr;
2291
2292
0
    CPLAssert(nullptr != pData);
2293
2294
0
    const bool bHasSubpixelShift =
2295
0
        psExtraArg->bFloatingPointWindowValidity &&
2296
0
        psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
2297
0
        (nXOff != psExtraArg->dfXOff || nYOff != psExtraArg->dfYOff);
2298
2299
0
    if (!bHasSubpixelShift && nXSize == nBufXSize && nYSize == nBufYSize &&
2300
0
        nBandCount > 1 &&
2301
0
        (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
2302
0
            nullptr &&
2303
0
        EQUAL(pszInterleave, "PIXEL"))
2304
0
    {
2305
0
        return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2306
0
                                  nBufXSize, nBufYSize, eBufType, nBandCount,
2307
0
                                  panBandMap, nPixelSpace, nLineSpace,
2308
0
                                  nBandSpace, psExtraArg);
2309
0
    }
2310
2311
0
    if (eRWFlag == GF_Read &&
2312
0
        (psExtraArg->eResampleAlg == GRIORA_Cubic ||
2313
0
         psExtraArg->eResampleAlg == GRIORA_CubicSpline ||
2314
0
         psExtraArg->eResampleAlg == GRIORA_Bilinear ||
2315
0
         psExtraArg->eResampleAlg == GRIORA_Lanczos) &&
2316
0
        !(nXSize == nBufXSize && nYSize == nBufYSize) && nBandCount > 1)
2317
0
    {
2318
0
        if (nBufXSize < nXSize && nBufYSize < nYSize && AreOverviewsEnabled())
2319
0
        {
2320
0
            int bTried = FALSE;
2321
0
            const CPLErr eErr = TryOverviewRasterIO(
2322
0
                eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize,
2323
0
                nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
2324
0
                nLineSpace, nBandSpace, psExtraArg, &bTried);
2325
0
            if (bTried)
2326
0
                return eErr;
2327
0
        }
2328
2329
0
        GDALDataType eFirstBandDT = GDT_Unknown;
2330
0
        int nFirstMaskFlags = 0;
2331
0
        GDALRasterBand *poFirstMaskBand = nullptr;
2332
0
        int nOKBands = 0;
2333
2334
        // Check if bands share the same mask band
2335
0
        for (int i = 0; i < nBandCount; ++i)
2336
0
        {
2337
0
            GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
2338
0
            if ((nBufXSize < nXSize || nBufYSize < nYSize) &&
2339
0
                poBand->GetOverviewCount())
2340
0
            {
2341
                // Could be improved to select the appropriate overview.
2342
0
                break;
2343
0
            }
2344
0
            if (poBand->GetColorTable() != nullptr)
2345
0
            {
2346
0
                break;
2347
0
            }
2348
0
            const GDALDataType eDT = poBand->GetRasterDataType();
2349
0
            if (GDALDataTypeIsComplex(eDT))
2350
0
            {
2351
0
                break;
2352
0
            }
2353
0
            if (i == 0)
2354
0
            {
2355
0
                eFirstBandDT = eDT;
2356
0
                nFirstMaskFlags = poBand->GetMaskFlags();
2357
0
                if (nFirstMaskFlags == GMF_NODATA)
2358
0
                {
2359
                    // The dataset-level resampling code is not ready for nodata
2360
                    // Fallback to band-level resampling
2361
0
                    break;
2362
0
                }
2363
0
                poFirstMaskBand = poBand->GetMaskBand();
2364
0
            }
2365
0
            else
2366
0
            {
2367
0
                if (eDT != eFirstBandDT)
2368
0
                {
2369
0
                    break;
2370
0
                }
2371
0
                int nMaskFlags = poBand->GetMaskFlags();
2372
0
                if (nMaskFlags == GMF_NODATA)
2373
0
                {
2374
                    // The dataset-level resampling code is not ready for nodata
2375
                    // Fallback to band-level resampling
2376
0
                    break;
2377
0
                }
2378
0
                GDALRasterBand *poMaskBand = poBand->GetMaskBand();
2379
0
                if (nFirstMaskFlags == GMF_ALL_VALID &&
2380
0
                    nMaskFlags == GMF_ALL_VALID)
2381
0
                {
2382
                    // Ok.
2383
0
                }
2384
0
                else if (poFirstMaskBand == poMaskBand)
2385
0
                {
2386
                    // Ok.
2387
0
                }
2388
0
                else
2389
0
                {
2390
0
                    break;
2391
0
                }
2392
0
            }
2393
2394
0
            ++nOKBands;
2395
0
        }
2396
2397
0
        GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2398
0
        void *pProgressDataGlobal = psExtraArg->pProgressData;
2399
2400
0
        CPLErr eErr = CE_None;
2401
0
        if (nOKBands > 0)
2402
0
        {
2403
0
            if (nOKBands < nBandCount)
2404
0
            {
2405
0
                psExtraArg->pfnProgress = GDALScaledProgress;
2406
0
                psExtraArg->pProgressData = GDALCreateScaledProgress(
2407
0
                    0.0, static_cast<double>(nOKBands) / nBandCount,
2408
0
                    pfnProgressGlobal, pProgressDataGlobal);
2409
0
                if (psExtraArg->pProgressData == nullptr)
2410
0
                    psExtraArg->pfnProgress = nullptr;
2411
0
            }
2412
2413
0
            eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2414
0
                                     pData, nBufXSize, nBufYSize, eBufType,
2415
0
                                     nOKBands, panBandMap, nPixelSpace,
2416
0
                                     nLineSpace, nBandSpace, psExtraArg);
2417
2418
0
            if (nOKBands < nBandCount)
2419
0
            {
2420
0
                GDALDestroyScaledProgress(psExtraArg->pProgressData);
2421
0
            }
2422
0
        }
2423
0
        if (eErr == CE_None && nOKBands < nBandCount)
2424
0
        {
2425
0
            if (nOKBands > 0)
2426
0
            {
2427
0
                psExtraArg->pfnProgress = GDALScaledProgress;
2428
0
                psExtraArg->pProgressData = GDALCreateScaledProgress(
2429
0
                    static_cast<double>(nOKBands) / nBandCount, 1.0,
2430
0
                    pfnProgressGlobal, pProgressDataGlobal);
2431
0
                if (psExtraArg->pProgressData == nullptr)
2432
0
                    psExtraArg->pfnProgress = nullptr;
2433
0
            }
2434
0
            eErr = BandBasedRasterIO(
2435
0
                eRWFlag, nXOff, nYOff, nXSize, nYSize,
2436
0
                static_cast<GByte *>(pData) + nBandSpace * nOKBands, nBufXSize,
2437
0
                nBufYSize, eBufType, nBandCount - nOKBands,
2438
0
                panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace,
2439
0
                psExtraArg);
2440
0
            if (nOKBands > 0)
2441
0
            {
2442
0
                GDALDestroyScaledProgress(psExtraArg->pProgressData);
2443
0
            }
2444
0
        }
2445
2446
0
        psExtraArg->pfnProgress = pfnProgressGlobal;
2447
0
        psExtraArg->pProgressData = pProgressDataGlobal;
2448
2449
0
        return eErr;
2450
0
    }
2451
2452
0
    return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2453
0
                             nBufXSize, nBufYSize, eBufType, nBandCount,
2454
0
                             panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2455
0
                             psExtraArg);
2456
0
}
2457
2458
//! @endcond
2459
2460
/************************************************************************/
2461
/*                         BandBasedRasterIO()                          */
2462
/*                                                                      */
2463
/*      Pass the request off to each band objects rasterio methods with */
2464
/*      appropriate arguments.                                          */
2465
/************************************************************************/
2466
2467
//! @cond Doxygen_Suppress
2468
CPLErr GDALDataset::BandBasedRasterIO(
2469
    GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
2470
    void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
2471
    int nBandCount, const int *panBandMap, GSpacing nPixelSpace,
2472
    GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
2473
2474
0
{
2475
0
    int iBandIndex;
2476
0
    CPLErr eErr = CE_None;
2477
2478
0
    GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
2479
0
    void *pProgressDataGlobal = psExtraArg->pProgressData;
2480
2481
0
    for (iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
2482
0
         ++iBandIndex)
2483
0
    {
2484
0
        GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
2485
2486
0
        if (poBand == nullptr)
2487
0
        {
2488
0
            eErr = CE_Failure;
2489
0
            break;
2490
0
        }
2491
2492
0
        GByte *pabyBandData =
2493
0
            static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
2494
2495
0
        if (nBandCount > 1)
2496
0
        {
2497
0
            psExtraArg->pfnProgress = GDALScaledProgress;
2498
0
            psExtraArg->pProgressData = GDALCreateScaledProgress(
2499
0
                1.0 * iBandIndex / nBandCount,
2500
0
                1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
2501
0
                pProgressDataGlobal);
2502
0
            if (psExtraArg->pProgressData == nullptr)
2503
0
                psExtraArg->pfnProgress = nullptr;
2504
0
        }
2505
2506
0
        eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2507
0
                                 pabyBandData, nBufXSize, nBufYSize, eBufType,
2508
0
                                 nPixelSpace, nLineSpace, psExtraArg);
2509
2510
0
        if (nBandCount > 1)
2511
0
            GDALDestroyScaledProgress(psExtraArg->pProgressData);
2512
0
    }
2513
2514
0
    psExtraArg->pfnProgress = pfnProgressGlobal;
2515
0
    psExtraArg->pProgressData = pProgressDataGlobal;
2516
2517
0
    return eErr;
2518
0
}
2519
2520
//! @endcond
2521
2522
/************************************************************************/
2523
/*               ValidateRasterIOOrAdviseReadParameters()               */
2524
/************************************************************************/
2525
2526
//! @cond Doxygen_Suppress
2527
CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
2528
    const char *pszCallingFunc, int *pbStopProcessingOnCENone, int nXOff,
2529
    int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize,
2530
    int nBandCount, const int *panBandMap)
2531
0
{
2532
2533
    /* -------------------------------------------------------------------- */
2534
    /*      Some size values are "noop".  Lets just return to avoid         */
2535
    /*      stressing lower level functions.                                */
2536
    /* -------------------------------------------------------------------- */
2537
0
    if (nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1)
2538
0
    {
2539
0
        CPLDebug("GDAL",
2540
0
                 "%s skipped for odd window or buffer size.\n"
2541
0
                 "  Window = (%d,%d)x%dx%d\n"
2542
0
                 "  Buffer = %dx%d",
2543
0
                 pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2544
0
                 nBufYSize);
2545
2546
0
        *pbStopProcessingOnCENone = TRUE;
2547
0
        return CE_None;
2548
0
    }
2549
2550
0
    CPLErr eErr = CE_None;
2551
0
    *pbStopProcessingOnCENone = FALSE;
2552
2553
0
    if (nXOff < 0 || nXOff > INT_MAX - nXSize ||
2554
0
        nXOff + nXSize > nRasterXSize || nYOff < 0 ||
2555
0
        nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize)
2556
0
    {
2557
0
        ReportError(CE_Failure, CPLE_IllegalArg,
2558
0
                    "Access window out of range in %s.  Requested "
2559
0
                    "(%d,%d) of size %dx%d on raster of %dx%d.",
2560
0
                    pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
2561
0
                    nRasterYSize);
2562
0
        eErr = CE_Failure;
2563
0
    }
2564
2565
0
    if (panBandMap == nullptr && nBandCount > GetRasterCount())
2566
0
    {
2567
0
        ReportError(CE_Failure, CPLE_IllegalArg,
2568
0
                    "%s: nBandCount cannot be greater than %d", pszCallingFunc,
2569
0
                    GetRasterCount());
2570
0
        eErr = CE_Failure;
2571
0
    }
2572
2573
0
    for (int i = 0; i < nBandCount && eErr == CE_None; ++i)
2574
0
    {
2575
0
        int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
2576
0
        if (iBand < 1 || iBand > GetRasterCount())
2577
0
        {
2578
0
            ReportError(
2579
0
                CE_Failure, CPLE_IllegalArg,
2580
0
                "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
2581
0
                pszCallingFunc, i, iBand);
2582
0
            eErr = CE_Failure;
2583
0
        }
2584
2585
0
        if (eErr == CE_None && GetRasterBand(iBand) == nullptr)
2586
0
        {
2587
0
            ReportError(
2588
0
                CE_Failure, CPLE_IllegalArg,
2589
0
                "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
2590
0
                pszCallingFunc, i, iBand);
2591
0
            eErr = CE_Failure;
2592
0
        }
2593
0
    }
2594
2595
0
    return eErr;
2596
0
}
2597
2598
//! @endcond
2599
2600
/************************************************************************/
2601
/*                              RasterIO()                              */
2602
/************************************************************************/
2603
2604
/**
2605
 * \brief Read/write a region of image data from multiple bands.
2606
 *
2607
 * This method allows reading a region of one or more GDALRasterBands from
2608
 * this dataset into a buffer,  or writing data from a buffer into a region
2609
 * of the GDALRasterBands.  It automatically takes care of data type
2610
 * translation if the data type (eBufType) of the buffer is different than
2611
 * that of the GDALRasterBand.
2612
 * The method also takes care of image decimation / replication if the
2613
 * buffer size (nBufXSize x nBufYSize) is different than the size of the
2614
 * region being accessed (nXSize x nYSize).
2615
 *
2616
 * The window of interest expressed by (nXOff, nYOff, nXSize, nYSize) should be
2617
 * fully within the raster space, that is nXOff >= 0, nYOff >= 0,
2618
 * nXOff + nXSize <= GetRasterXSize() and nYOff + nYSize <= GetRasterYSize().
2619
 * If reads larger than the raster space are wished, GDALTranslate() might be used.
2620
 * Or use nLineSpace and a possibly shifted pData value.
2621
 *
2622
 * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
2623
 * writing from various organization of buffers.
2624
 *
2625
 * Some formats may efficiently implement decimation into a buffer by
2626
 * reading from lower resolution overview images. The logic of the default
2627
 * implementation in the base class GDALRasterBand is the following one. It
2628
 * computes a target_downscaling_factor from the window of interest and buffer
2629
 * size which is min(nXSize/nBufXSize, nYSize/nBufYSize).
2630
 * It then walks through overviews and will select the first one whose
2631
 * downscaling factor is greater than target_downscaling_factor / 1.2.
2632
 *
2633
 * Let's assume we have overviews at downscaling factors 2, 4 and 8.
2634
 * The relationship between target_downscaling_factor and the select overview
2635
 * level is the following one:
2636
 *
2637
 * target_downscaling_factor  | selected_overview
2638
 * -------------------------  | -----------------
2639
 * ]0,       2 / 1.2]         | full resolution band
2640
 * ]2 / 1.2, 4 / 1.2]         | 2x downsampled band
2641
 * ]4 / 1.2, 8 / 1.2]         | 4x downsampled band
2642
 * ]8 / 1.2, infinity[        | 8x downsampled band
2643
 *
2644
 * Note that starting with GDAL 3.9, this 1.2 oversampling factor can be
2645
 * modified by setting the GDAL_OVERVIEW_OVERSAMPLING_THRESHOLD configuration
2646
 * option. Also note that starting with GDAL 3.9, when the resampling algorithm
2647
 * specified in psExtraArg->eResampleAlg is different from GRIORA_NearestNeighbour,
2648
 * this oversampling threshold defaults to 1. Consequently if there are overviews
2649
 * of downscaling factor 2, 4 and 8, and the desired downscaling factor is
2650
 * 7.99, the overview of factor 4 will be selected for a non nearest resampling.
2651
 *
2652
 * For highest performance full resolution data access, read and write
2653
 * on "block boundaries" as returned by GetBlockSize(), or use the
2654
 * ReadBlock() and WriteBlock() methods.
2655
 *
2656
 * This method is the same as the C GDALDatasetRasterIO() or
2657
 * GDALDatasetRasterIOEx() functions.
2658
 *
2659
 * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
2660
 * write a region of data.
2661
 *
2662
 * @param nXOff The pixel offset to the top left corner of the region
2663
 * of the band to be accessed.  This would be zero to start from the left side.
2664
 *
2665
 * @param nYOff The line offset to the top left corner of the region
2666
 * of the band to be accessed.  This would be zero to start from the top.
2667
 *
2668
 * @param nXSize The width of the region of the band to be accessed in pixels.
2669
 *
2670
 * @param nYSize The height of the region of the band to be accessed in lines.
2671
 *
2672
 * @param pData The buffer into which the data should be read, or from which
2673
 * it should be written.  This buffer must contain at least
2674
 * nBufXSize * nBufYSize * nBandCount words of type eBufType.  It is organized
2675
 * in left to right,top to bottom pixel order.  Spacing is controlled by the
2676
 * nPixelSpace, and nLineSpace parameters.
2677
 * Note that even with eRWFlag==GF_Write, the content of the buffer might be
2678
 * temporarily modified during the execution of this method (and eventually
2679
 * restored back to its original content), so it is not safe to use a buffer
2680
 * stored in a read-only section of the calling program.
2681
 *
2682
 * @param nBufXSize the width of the buffer image into which the desired region
2683
 * is to be read, or from which it is to be written.
2684
 *
2685
 * @param nBufYSize the height of the buffer image into which the desired
2686
 * region is to be read, or from which it is to be written.
2687
 *
2688
 * @param eBufType the type of the pixel values in the pData data buffer. The
2689
 * pixel values will automatically be translated to/from the GDALRasterBand
2690
 * data type as needed. Most driver implementations will use GDALCopyWords64()
2691
 * to perform data type translation.
2692
 *
2693
 * @param nBandCount the number of bands being read or written.
2694
 *
2695
 * @param panBandMap the list of nBandCount band numbers being read/written.
2696
 * Note band numbers are 1 based. This may be NULL to select the first
2697
 * nBandCount bands. (Note: before GDAL 3.10, argument type was "int*", and
2698
 * not "const int*")
2699
 *
2700
 * @param nPixelSpace The byte offset from the start of one pixel value in
2701
 * pData to the start of the next pixel value within a scanline. If defaulted
2702
 * (0) the size of the datatype eBufType is used.
2703
 *
2704
 * @param nLineSpace The byte offset from the start of one scanline in
2705
 * pData to the start of the next. If defaulted (0) the size of the datatype
2706
 * eBufType * nBufXSize is used.
2707
 *
2708
 * @param nBandSpace the byte offset from the start of one bands data to the
2709
 * start of the next. If defaulted (0) the value will be
2710
 * nLineSpace * nBufYSize implying band sequential organization
2711
 * of the data buffer.
2712
 *
2713
 * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
2714
 * structure with additional arguments to specify resampling and progress
2715
 * callback, or NULL for default behavior. The GDAL_RASTERIO_RESAMPLING
2716
 * configuration option can also be defined to override the default resampling
2717
 * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
2718
 *
2719
 * @return CE_Failure if the access fails, otherwise CE_None.
2720
 */
2721
2722
CPLErr GDALDataset::RasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2723
                             int nXSize, int nYSize, void *pData, int nBufXSize,
2724
                             int nBufYSize, GDALDataType eBufType,
2725
                             int nBandCount, const int *panBandMap,
2726
                             GSpacing nPixelSpace, GSpacing nLineSpace,
2727
                             GSpacing nBandSpace,
2728
                             GDALRasterIOExtraArg *psExtraArg)
2729
2730
0
{
2731
0
    GDALRasterIOExtraArg sExtraArg;
2732
0
    if (psExtraArg == nullptr)
2733
0
    {
2734
0
        INIT_RASTERIO_EXTRA_ARG(sExtraArg);
2735
2736
        // 4 below inits are not strictly needed but make Coverity Scan
2737
        // happy
2738
0
        sExtraArg.dfXOff = nXOff;
2739
0
        sExtraArg.dfYOff = nYOff;
2740
0
        sExtraArg.dfXSize = nXSize;
2741
0
        sExtraArg.dfYSize = nYSize;
2742
2743
0
        psExtraArg = &sExtraArg;
2744
0
    }
2745
0
    else if (CPL_UNLIKELY(psExtraArg->nVersion >
2746
0
                          RASTERIO_EXTRA_ARG_CURRENT_VERSION))
2747
0
    {
2748
0
        ReportError(CE_Failure, CPLE_AppDefined,
2749
0
                    "Unhandled version of GDALRasterIOExtraArg");
2750
0
        return CE_Failure;
2751
0
    }
2752
2753
0
    GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
2754
0
                                       nBufYSize);
2755
2756
0
    if (CPL_UNLIKELY(nullptr == pData))
2757
0
    {
2758
0
        ReportError(CE_Failure, CPLE_AppDefined,
2759
0
                    "The buffer into which the data should be read is null");
2760
0
        return CE_Failure;
2761
0
    }
2762
2763
    /* -------------------------------------------------------------------- */
2764
    /*      Do some validation of parameters.                               */
2765
    /* -------------------------------------------------------------------- */
2766
2767
0
    if (CPL_UNLIKELY(eRWFlag != GF_Read && eRWFlag != GF_Write))
2768
0
    {
2769
0
        ReportError(
2770
0
            CE_Failure, CPLE_IllegalArg,
2771
0
            "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
2772
0
            eRWFlag);
2773
0
        return CE_Failure;
2774
0
    }
2775
2776
0
    if (eRWFlag == GF_Write)
2777
0
    {
2778
0
        if (CPL_UNLIKELY(eAccess != GA_Update))
2779
0
        {
2780
0
            ReportError(CE_Failure, CPLE_AppDefined,
2781
0
                        "Write operation not permitted on dataset opened "
2782
0
                        "in read-only mode");
2783
0
            return CE_Failure;
2784
0
        }
2785
0
    }
2786
2787
0
    int bStopProcessing = FALSE;
2788
0
    CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
2789
0
        "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
2790
0
        nBufYSize, nBandCount, panBandMap);
2791
0
    if (eErr != CE_None || bStopProcessing)
2792
0
        return eErr;
2793
0
    if (CPL_UNLIKELY(eBufType == GDT_Unknown || eBufType == GDT_TypeCount))
2794
0
    {
2795
0
        ReportError(CE_Failure, CPLE_AppDefined,
2796
0
                    "Illegal GDT_Unknown/GDT_TypeCount argument");
2797
0
        return CE_Failure;
2798
0
    }
2799
2800
    /* -------------------------------------------------------------------- */
2801
    /*      If pixel and line spacing are defaulted assign reasonable      */
2802
    /*      value assuming a packed buffer.                                 */
2803
    /* -------------------------------------------------------------------- */
2804
0
    if (nPixelSpace == 0)
2805
0
        nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
2806
2807
0
    if (nLineSpace == 0)
2808
0
    {
2809
0
        nLineSpace = nPixelSpace * nBufXSize;
2810
0
    }
2811
2812
0
    if (nBandSpace == 0 && nBandCount > 1)
2813
0
    {
2814
0
        nBandSpace = nLineSpace * nBufYSize;
2815
0
    }
2816
2817
0
    if (panBandMap == nullptr)
2818
0
    {
2819
0
        if (!m_poPrivate)
2820
0
            return CE_Failure;
2821
0
        CPLAssert(static_cast<int>(m_poPrivate->m_anBandMap.size()) == nBands);
2822
0
        panBandMap = m_poPrivate->m_anBandMap.data();
2823
0
    }
2824
2825
0
    int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
2826
2827
    /* -------------------------------------------------------------------- */
2828
    /*      We are being forced to use cached IO instead of a driver        */
2829
    /*      specific implementation.                                        */
2830
    /* -------------------------------------------------------------------- */
2831
0
    if (bForceCachedIO)
2832
0
    {
2833
0
        eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2834
0
                                  nBufXSize, nBufYSize, eBufType, nBandCount,
2835
0
                                  panBandMap, nPixelSpace, nLineSpace,
2836
0
                                  nBandSpace, psExtraArg);
2837
0
    }
2838
2839
    /* -------------------------------------------------------------------- */
2840
    /*      Call the format specific function.                              */
2841
    /* -------------------------------------------------------------------- */
2842
0
    else
2843
0
    {
2844
0
        eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2845
0
                         nBufXSize, nBufYSize, eBufType, nBandCount,
2846
                         // TODO: remove this const_cast once IRasterIO()
2847
                         // takes a const int*
2848
0
                         const_cast<int *>(panBandMap), nPixelSpace, nLineSpace,
2849
0
                         nBandSpace, psExtraArg);
2850
0
    }
2851
2852
0
    if (bCallLeaveReadWrite)
2853
0
        LeaveReadWrite();
2854
2855
0
    return eErr;
2856
0
}
2857
2858
/************************************************************************/
2859
/*                        GDALDatasetRasterIO()                         */
2860
/************************************************************************/
2861
2862
/**
2863
 * \brief Read/write a region of image data from multiple bands.
2864
 *
2865
 * Use GDALDatasetRasterIOEx() if 64 bit spacings or extra arguments (resampling
2866
 * resolution, progress callback, etc. are needed)
2867
 *
2868
 * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
2869
 *
2870
 * @see GDALDataset::RasterIO()
2871
 */
2872
2873
CPLErr CPL_STDCALL GDALDatasetRasterIO(GDALDatasetH hDS, GDALRWFlag eRWFlag,
2874
                                       int nXOff, int nYOff, int nXSize,
2875
                                       int nYSize, void *pData, int nBufXSize,
2876
                                       int nBufYSize, GDALDataType eBufType,
2877
                                       int nBandCount, const int *panBandMap,
2878
                                       int nPixelSpace, int nLineSpace,
2879
                                       int nBandSpace)
2880
2881
0
{
2882
0
    VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
2883
2884
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2885
2886
0
    return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2887
0
                          nBufXSize, nBufYSize, eBufType, nBandCount,
2888
0
                          panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2889
0
                          nullptr);
2890
0
}
2891
2892
/************************************************************************/
2893
/*                       GDALDatasetRasterIOEx()                        */
2894
/************************************************************************/
2895
2896
/**
2897
 * \brief Read/write a region of image data from multiple bands.
2898
 *
2899
 * Note: before GDAL 3.10, panBandMap type was "int*", and not "const int*"
2900
 *
2901
 * @see GDALDataset::RasterIO()
2902
 * @since GDAL 2.0
2903
 */
2904
2905
CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
2906
    GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
2907
    int nYSize, void *pData, int nBufXSize, int nBufYSize,
2908
    GDALDataType eBufType, int nBandCount, const int *panBandMap,
2909
    GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
2910
    GDALRasterIOExtraArg *psExtraArg)
2911
2912
0
{
2913
0
    VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
2914
2915
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
2916
2917
0
    return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
2918
0
                          nBufXSize, nBufYSize, eBufType, nBandCount,
2919
0
                          panBandMap, nPixelSpace, nLineSpace, nBandSpace,
2920
0
                          psExtraArg);
2921
0
}
2922
2923
/************************************************************************/
2924
/*                          GetOpenDatasets()                           */
2925
/************************************************************************/
2926
2927
/**
2928
 * \brief Fetch all open GDAL dataset handles.
2929
 *
2930
 * This method is the same as the C function GDALGetOpenDatasets().
2931
 *
2932
 * NOTE: This method is not thread safe.  The returned list may change
2933
 * at any time and it should not be freed.
2934
 *
2935
 * @param pnCount integer into which to place the count of dataset pointers
2936
 * being returned.
2937
 *
2938
 * @return a pointer to an array of dataset handles.
2939
 */
2940
2941
GDALDataset **GDALDataset::GetOpenDatasets(int *pnCount)
2942
2943
0
{
2944
0
    CPLMutexHolderD(&hDLMutex);
2945
2946
0
    if (poAllDatasetMap == nullptr)
2947
0
    {
2948
0
        *pnCount = 0;
2949
0
        return nullptr;
2950
0
    }
2951
2952
0
    *pnCount = static_cast<int>(poAllDatasetMap->size());
2953
0
    ppDatasets = static_cast<GDALDataset **>(
2954
0
        CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
2955
0
    std::map<GDALDataset *, GIntBig>::iterator oIter = poAllDatasetMap->begin();
2956
0
    for (int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i)
2957
0
        ppDatasets[i] = oIter->first;
2958
0
    return ppDatasets;
2959
0
}
2960
2961
/************************************************************************/
2962
/*                        GDALGetOpenDatasets()                         */
2963
/************************************************************************/
2964
2965
/**
2966
 * \brief Fetch all open GDAL dataset handles.
2967
 *
2968
 * @see GDALDataset::GetOpenDatasets()
2969
 */
2970
2971
void CPL_STDCALL GDALGetOpenDatasets(GDALDatasetH **ppahDSList, int *pnCount)
2972
2973
0
{
2974
0
    VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
2975
0
    VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
2976
2977
0
    *ppahDSList =
2978
0
        reinterpret_cast<GDALDatasetH *>(GDALDataset::GetOpenDatasets(pnCount));
2979
0
}
2980
2981
/************************************************************************/
2982
/*                        GDALCleanOpenDatasetsList()                   */
2983
/************************************************************************/
2984
2985
// Useful when called from the child of a fork(), to avoid closing
2986
// the datasets of the parent at the child termination.
2987
void GDALNullifyOpenDatasetsList()
2988
0
{
2989
0
    poAllDatasetMap = nullptr;
2990
0
    phSharedDatasetSet = nullptr;
2991
0
    ppDatasets = nullptr;
2992
0
    hDLMutex = nullptr;
2993
0
}
2994
2995
/************************************************************************/
2996
/*                             GDALGetAccess()                          */
2997
/************************************************************************/
2998
2999
/**
3000
 * \brief Return access flag
3001
 *
3002
 * @see GDALDataset::GetAccess()
3003
 */
3004
3005
int CPL_STDCALL GDALGetAccess(GDALDatasetH hDS)
3006
0
{
3007
0
    VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
3008
3009
0
    return GDALDataset::FromHandle(hDS)->GetAccess();
3010
0
}
3011
3012
/************************************************************************/
3013
/*                             AdviseRead()                             */
3014
/************************************************************************/
3015
3016
/**
3017
 * \brief Advise driver of upcoming read requests.
3018
 *
3019
 * Some GDAL drivers operate more efficiently if they know in advance what
3020
 * set of upcoming read requests will be made.  The AdviseRead() method allows
3021
 * an application to notify the driver of the region and bands of interest,
3022
 * and at what resolution the region will be read.
3023
 *
3024
 * Many drivers just ignore the AdviseRead() call, but it can dramatically
3025
 * accelerate access via some drivers.
3026
 *
3027
 * Depending on call paths, drivers might receive several calls to
3028
 * AdviseRead() with the same parameters.
3029
 *
3030
 * @param nXOff The pixel offset to the top left corner of the region
3031
 * of the band to be accessed.  This would be zero to start from the left side.
3032
 *
3033
 * @param nYOff The line offset to the top left corner of the region
3034
 * of the band to be accessed.  This would be zero to start from the top.
3035
 *
3036
 * @param nXSize The width of the region of the band to be accessed in pixels.
3037
 *
3038
 * @param nYSize The height of the region of the band to be accessed in lines.
3039
 *
3040
 * @param nBufXSize the width of the buffer image into which the desired region
3041
 * is to be read, or from which it is to be written.
3042
 *
3043
 * @param nBufYSize the height of the buffer image into which the desired
3044
 * region is to be read, or from which it is to be written.
3045
 *
3046
 * @param eBufType the type of the pixel values in the pData data buffer.  The
3047
 * pixel values will automatically be translated to/from the GDALRasterBand
3048
 * data type as needed.
3049
 *
3050
 * @param nBandCount the number of bands being read or written.
3051
 *
3052
 * @param panBandMap the list of nBandCount band numbers being read/written.
3053
 * Note band numbers are 1 based.   This may be NULL to select the first
3054
 * nBandCount bands.
3055
 *
3056
 * @param papszOptions a list of name=value strings with special control
3057
 * options.  Normally this is NULL.
3058
 *
3059
 * @return CE_Failure if the request is invalid and CE_None if it works or
3060
 * is ignored.
3061
 */
3062
3063
CPLErr GDALDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
3064
                               int nBufXSize, int nBufYSize,
3065
                               GDALDataType eBufType, int nBandCount,
3066
                               int *panBandMap, char **papszOptions)
3067
3068
0
{
3069
    /* -------------------------------------------------------------------- */
3070
    /*      Do some validation of parameters.                               */
3071
    /* -------------------------------------------------------------------- */
3072
0
    int bStopProcessing = FALSE;
3073
0
    CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
3074
0
        "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
3075
0
        nBufXSize, nBufYSize, nBandCount, panBandMap);
3076
0
    if (eErr != CE_None || bStopProcessing)
3077
0
        return eErr;
3078
3079
0
    for (int iBand = 0; iBand < nBandCount; ++iBand)
3080
0
    {
3081
0
        GDALRasterBand *poBand = nullptr;
3082
3083
0
        if (panBandMap == nullptr)
3084
0
            poBand = GetRasterBand(iBand + 1);
3085
0
        else
3086
0
            poBand = GetRasterBand(panBandMap[iBand]);
3087
3088
0
        if (poBand == nullptr)
3089
0
            return CE_Failure;
3090
3091
0
        eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
3092
0
                                  nBufYSize, eBufType, papszOptions);
3093
3094
0
        if (eErr != CE_None)
3095
0
            return eErr;
3096
0
    }
3097
3098
0
    return CE_None;
3099
0
}
3100
3101
/************************************************************************/
3102
/*                       GDALDatasetAdviseRead()                        */
3103
/************************************************************************/
3104
3105
/**
3106
 * \brief Advise driver of upcoming read requests.
3107
 *
3108
 * @see GDALDataset::AdviseRead()
3109
 */
3110
CPLErr CPL_STDCALL GDALDatasetAdviseRead(GDALDatasetH hDS, int nXOff, int nYOff,
3111
                                         int nXSize, int nYSize, int nBufXSize,
3112
                                         int nBufYSize, GDALDataType eDT,
3113
                                         int nBandCount, int *panBandMap,
3114
                                         CSLConstList papszOptions)
3115
3116
0
{
3117
0
    VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
3118
3119
0
    return GDALDataset::FromHandle(hDS)->AdviseRead(
3120
0
        nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount,
3121
0
        panBandMap, const_cast<char **>(papszOptions));
3122
0
}
3123
3124
/************************************************************************/
3125
/*                         GDALAntiRecursionStruct                      */
3126
/************************************************************************/
3127
3128
// Prevent infinite recursion.
3129
struct GDALAntiRecursionStruct
3130
{
3131
    struct DatasetContext
3132
    {
3133
        std::string osFilename;
3134
        int nOpenFlags;
3135
        std::string osAllowedDrivers;
3136
3137
        DatasetContext(const std::string &osFilenameIn, int nOpenFlagsIn,
3138
                       const std::string &osAllowedDriversIn)
3139
0
            : osFilename(osFilenameIn), nOpenFlags(nOpenFlagsIn),
3140
0
              osAllowedDrivers(osAllowedDriversIn)
3141
0
        {
3142
0
        }
3143
    };
3144
3145
    struct DatasetContextCompare
3146
    {
3147
        bool operator()(const DatasetContext &lhs,
3148
                        const DatasetContext &rhs) const
3149
0
        {
3150
0
            return lhs.osFilename < rhs.osFilename ||
3151
0
                   (lhs.osFilename == rhs.osFilename &&
3152
0
                    (lhs.nOpenFlags < rhs.nOpenFlags ||
3153
0
                     (lhs.nOpenFlags == rhs.nOpenFlags &&
3154
0
                      lhs.osAllowedDrivers < rhs.osAllowedDrivers)));
3155
0
        }
3156
    };
3157
3158
    std::set<DatasetContext, DatasetContextCompare> aosDatasetNamesWithFlags{};
3159
    int nRecLevel = 0;
3160
    std::map<std::string, int> m_oMapDepth{};
3161
};
3162
3163
#ifdef _WIN32
3164
// Currently thread_local and C++ objects don't work well with DLL on Windows
3165
static void FreeAntiRecursionOpen(void *pData)
3166
{
3167
    delete static_cast<GDALAntiRecursionStruct *>(pData);
3168
}
3169
3170
static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3171
{
3172
    static GDALAntiRecursionStruct dummy;
3173
    int bMemoryErrorOccurred = false;
3174
    void *pData =
3175
        CPLGetTLSEx(CTLS_GDALOPEN_ANTIRECURSION, &bMemoryErrorOccurred);
3176
    if (bMemoryErrorOccurred)
3177
    {
3178
        return dummy;
3179
    }
3180
    if (pData == nullptr)
3181
    {
3182
        auto pAntiRecursion = new GDALAntiRecursionStruct();
3183
        CPLSetTLSWithFreeFuncEx(CTLS_GDALOPEN_ANTIRECURSION, pAntiRecursion,
3184
                                FreeAntiRecursionOpen, &bMemoryErrorOccurred);
3185
        if (bMemoryErrorOccurred)
3186
        {
3187
            delete pAntiRecursion;
3188
            return dummy;
3189
        }
3190
        return *pAntiRecursion;
3191
    }
3192
    return *static_cast<GDALAntiRecursionStruct *>(pData);
3193
}
3194
#else
3195
static thread_local GDALAntiRecursionStruct g_tls_antiRecursion;
3196
3197
static GDALAntiRecursionStruct &GetAntiRecursionOpen()
3198
0
{
3199
0
    return g_tls_antiRecursion;
3200
0
}
3201
#endif
3202
3203
//! @cond Doxygen_Suppress
3204
GDALAntiRecursionGuard::GDALAntiRecursionGuard(const std::string &osIdentifier)
3205
0
    : m_psAntiRecursionStruct(&GetAntiRecursionOpen()),
3206
0
      m_osIdentifier(osIdentifier),
3207
0
      m_nDepth(++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3208
0
{
3209
0
    CPLAssert(!osIdentifier.empty());
3210
0
}
3211
3212
GDALAntiRecursionGuard::GDALAntiRecursionGuard(
3213
    const GDALAntiRecursionGuard &other, const std::string &osIdentifier)
3214
0
    : m_psAntiRecursionStruct(other.m_psAntiRecursionStruct),
3215
0
      m_osIdentifier(osIdentifier.empty()
3216
0
                         ? osIdentifier
3217
0
                         : other.m_osIdentifier + osIdentifier),
3218
0
      m_nDepth(m_osIdentifier.empty()
3219
0
                   ? 0
3220
0
                   : ++m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier])
3221
0
{
3222
0
}
3223
3224
GDALAntiRecursionGuard::~GDALAntiRecursionGuard()
3225
0
{
3226
0
    if (!m_osIdentifier.empty())
3227
0
    {
3228
0
        --m_psAntiRecursionStruct->m_oMapDepth[m_osIdentifier];
3229
0
    }
3230
0
}
3231
3232
//! @endcond
3233
3234
/************************************************************************/
3235
/*                            GetFileList()                             */
3236
/************************************************************************/
3237
3238
/**
3239
 * \brief Fetch files forming dataset.
3240
 *
3241
 * Returns a list of files believed to be part of this dataset.  If it returns
3242
 * an empty list of files it means there is believed to be no local file
3243
 * system files associated with the dataset (for instance a virtual dataset).
3244
 * The returned file list is owned by the caller and should be deallocated
3245
 * with CSLDestroy().
3246
 *
3247
 * The returned filenames will normally be relative or absolute paths
3248
 * depending on the path used to originally open the dataset.  The strings
3249
 * will be UTF-8 encoded.
3250
 *
3251
 * This method is the same as the C GDALGetFileList() function.
3252
 *
3253
 * @return NULL or a NULL terminated array of file names.
3254
 */
3255
3256
char **GDALDataset::GetFileList()
3257
3258
0
{
3259
0
    CPLString osMainFilename = GetDescription();
3260
0
    VSIStatBufL sStat;
3261
3262
0
    GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3263
0
    GDALAntiRecursionStruct::DatasetContext datasetCtxt(osMainFilename, 0,
3264
0
                                                        std::string());
3265
0
    auto &aosDatasetList = sAntiRecursion.aosDatasetNamesWithFlags;
3266
0
    if (cpl::contains(aosDatasetList, datasetCtxt))
3267
0
        return nullptr;
3268
3269
    /* -------------------------------------------------------------------- */
3270
    /*      Is the main filename even a real filesystem object?             */
3271
    /* -------------------------------------------------------------------- */
3272
0
    int bMainFileReal =
3273
0
        VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
3274
3275
    /* -------------------------------------------------------------------- */
3276
    /*      Form new list.                                                  */
3277
    /* -------------------------------------------------------------------- */
3278
0
    char **papszList = nullptr;
3279
3280
0
    if (bMainFileReal)
3281
0
        papszList = CSLAddString(papszList, osMainFilename);
3282
3283
0
    if (sAntiRecursion.nRecLevel == 100)
3284
0
    {
3285
0
        CPLError(CE_Failure, CPLE_AppDefined,
3286
0
                 "GetFileList() called with too many recursion levels");
3287
0
        return papszList;
3288
0
    }
3289
0
    ++sAntiRecursion.nRecLevel;
3290
3291
    /* -------------------------------------------------------------------- */
3292
    /*      Do we have a known overview file?                               */
3293
    /* -------------------------------------------------------------------- */
3294
0
    if (oOvManager.IsInitialized() && oOvManager.poODS != nullptr)
3295
0
    {
3296
0
        auto iter = aosDatasetList.insert(datasetCtxt).first;
3297
0
        char **papszOvrList = oOvManager.poODS->GetFileList();
3298
0
        papszList = CSLInsertStrings(papszList, -1, papszOvrList);
3299
0
        CSLDestroy(papszOvrList);
3300
0
        aosDatasetList.erase(iter);
3301
0
    }
3302
3303
    /* -------------------------------------------------------------------- */
3304
    /*      Do we have a known mask file?                                   */
3305
    /* -------------------------------------------------------------------- */
3306
0
    if (oOvManager.HaveMaskFile())
3307
0
    {
3308
0
        auto iter = aosDatasetList.insert(std::move(datasetCtxt)).first;
3309
0
        for (const char *pszFile :
3310
0
             CPLStringList(oOvManager.poMaskDS->GetFileList()))
3311
0
        {
3312
0
            if (CSLFindString(papszList, pszFile) < 0)
3313
0
                papszList = CSLAddString(papszList, pszFile);
3314
0
        }
3315
0
        aosDatasetList.erase(iter);
3316
0
    }
3317
3318
0
    --sAntiRecursion.nRecLevel;
3319
3320
0
    return papszList;
3321
0
}
3322
3323
/************************************************************************/
3324
/*                          GDALGetFileList()                           */
3325
/************************************************************************/
3326
3327
/**
3328
 * \brief Fetch files forming dataset.
3329
 *
3330
 * @see GDALDataset::GetFileList()
3331
 */
3332
3333
char **CPL_STDCALL GDALGetFileList(GDALDatasetH hDS)
3334
3335
0
{
3336
0
    VALIDATE_POINTER1(hDS, "GDALGetFileList", nullptr);
3337
3338
0
    return GDALDataset::FromHandle(hDS)->GetFileList();
3339
0
}
3340
3341
/************************************************************************/
3342
/*                           CreateMaskBand()                           */
3343
/************************************************************************/
3344
3345
/**
3346
 * \brief Adds a mask band to the dataset
3347
 *
3348
 * The default implementation of the CreateMaskBand() method is implemented
3349
 * based on similar rules to the .ovr handling implemented using the
3350
 * GDALDefaultOverviews object. A TIFF file with the extension .msk will
3351
 * be created with the same basename as the original file, and it will have
3352
 * one band.
3353
 * The mask images will be deflate compressed tiled images with the same
3354
 * block size as the original image if possible.
3355
 * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
3356
 * level, where xx matches the band number of a band of the main dataset. The
3357
 * value of those items will be the one of the nFlagsIn parameter.
3358
 *
3359
 * Note that if you got a mask band with a previous call to GetMaskBand(), it
3360
 * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
3361
 * again.
3362
 *
3363
 * @since GDAL 1.5.0
3364
 *
3365
 * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
3366
 *                 GMF_PER_DATASET will be always set, even if not explicitly
3367
 *                 specified.
3368
 * @return CE_None on success or CE_Failure on an error.
3369
 *
3370
 * @see https://gdal.org/development/rfc/rfc15_nodatabitmask.html
3371
 * @see GDALRasterBand::CreateMaskBand()
3372
 *
3373
 */
3374
CPLErr GDALDataset::CreateMaskBand(int nFlagsIn)
3375
3376
0
{
3377
0
    if (oOvManager.IsInitialized())
3378
0
    {
3379
0
        CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
3380
0
        if (eErr != CE_None)
3381
0
            return eErr;
3382
3383
        // Invalidate existing raster band masks.
3384
0
        for (int i = 0; i < nBands; ++i)
3385
0
        {
3386
0
            GDALRasterBand *poBand = papoBands[i];
3387
0
            poBand->poMask.reset();
3388
0
        }
3389
3390
0
        return CE_None;
3391
0
    }
3392
3393
0
    ReportError(CE_Failure, CPLE_NotSupported,
3394
0
                "CreateMaskBand() not supported for this dataset.");
3395
3396
0
    return CE_Failure;
3397
0
}
3398
3399
/************************************************************************/
3400
/*                     GDALCreateDatasetMaskBand()                      */
3401
/************************************************************************/
3402
3403
/**
3404
 * \brief Adds a mask band to the dataset
3405
 * @see GDALDataset::CreateMaskBand()
3406
 */
3407
CPLErr CPL_STDCALL GDALCreateDatasetMaskBand(GDALDatasetH hDS, int nFlags)
3408
3409
0
{
3410
0
    VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
3411
3412
0
    return GDALDataset::FromHandle(hDS)->CreateMaskBand(nFlags);
3413
0
}
3414
3415
/************************************************************************/
3416
/*                              GDALOpen()                              */
3417
/************************************************************************/
3418
3419
/**
3420
 * \brief Open a raster file as a GDALDataset.
3421
 *
3422
 * This function will try to open the passed file, or virtual dataset
3423
 * name by invoking the Open method of each registered GDALDriver in turn.
3424
 * The first successful open will result in a returned dataset.  If all
3425
 * drivers fail then NULL is returned and an error is issued.
3426
 *
3427
 * Several recommendations :
3428
 * <ul>
3429
 * <li>If you open a dataset object with GA_Update access, it is not recommended
3430
 * to open a new dataset on the same underlying file.</li>
3431
 * <li>The returned dataset should only be accessed by one thread at a time. If
3432
 * you want to use it from different threads, you must add all necessary code
3433
 * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
3434
 * as GeoTIFF, maintain internal state variables that are updated each time a
3435
 * new block is read, thus preventing concurrent use.) </li>
3436
 * </ul>
3437
 *
3438
 * For drivers supporting the VSI virtual file API, it is possible to open a
3439
 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3440
 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3441
 * server (see VSIInstallCurlFileHandler())
3442
 *
3443
 * \sa GDALOpenShared()
3444
 * \sa GDALOpenEx()
3445
 *
3446
 * @param pszFilename the name of the file to access.  In the case of
3447
 * exotic drivers this may not refer to a physical file, but instead contain
3448
 * information for the driver on how to access a dataset.  It should be in UTF-8
3449
 * encoding.
3450
 *
3451
 * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
3452
 * drivers support only read only access.
3453
 *
3454
 * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
3455
 * this handle can be cast to a GDALDataset *.
3456
 */
3457
3458
GDALDatasetH CPL_STDCALL GDALOpen(const char *pszFilename, GDALAccess eAccess)
3459
3460
0
{
3461
0
    const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
3462
0
    const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
3463
0
    GDALDatasetH hDataset =
3464
0
        GDALOpenEx(pszFilename, nOpenFlags, nullptr, nullptr, nullptr);
3465
0
    return hDataset;
3466
0
}
3467
3468
/************************************************************************/
3469
/*                             GetSharedDS()                            */
3470
/************************************************************************/
3471
3472
static GDALDataset *GetSharedDS(const char *pszFilename,
3473
                                unsigned int nOpenFlags,
3474
                                const char *const *papszOpenOptions)
3475
0
{
3476
0
    CPLMutexHolderD(&hDLMutex);
3477
3478
0
    if (phSharedDatasetSet != nullptr)
3479
0
    {
3480
0
        const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
3481
0
        SharedDatasetCtxt sStruct;
3482
3483
0
        sStruct.nPID = nThisPID;
3484
0
        sStruct.pszDescription = const_cast<char *>(pszFilename);
3485
0
        sStruct.nOpenFlags = nOpenFlags & ~GDAL_OF_SHARED;
3486
0
        std::string osConcatenatedOpenOptions =
3487
0
            GDALSharedDatasetConcatenateOpenOptions(papszOpenOptions);
3488
0
        sStruct.pszConcatenatedOpenOptions = &osConcatenatedOpenOptions[0];
3489
0
        sStruct.poDS = nullptr;
3490
0
        SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
3491
0
            CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3492
0
        if (psStruct == nullptr && (nOpenFlags & GDAL_OF_UPDATE) == 0)
3493
0
        {
3494
0
            sStruct.nOpenFlags |= GDAL_OF_UPDATE;
3495
0
            psStruct = static_cast<SharedDatasetCtxt *>(
3496
0
                CPLHashSetLookup(phSharedDatasetSet, &sStruct));
3497
0
        }
3498
0
        if (psStruct)
3499
0
        {
3500
0
            return psStruct->poDS;
3501
0
        }
3502
0
    }
3503
0
    return nullptr;
3504
0
}
3505
3506
/************************************************************************/
3507
/*                             GDALOpenEx()                             */
3508
/************************************************************************/
3509
3510
/**
3511
 * \brief Open a raster or vector file as a GDALDataset.
3512
 *
3513
 * This function will try to open the passed file, or virtual dataset
3514
 * name by invoking the Open method of each registered GDALDriver in turn.
3515
 * The first successful open will result in a returned dataset.  If all
3516
 * drivers fail then NULL is returned and an error is issued.
3517
 *
3518
 * Several recommendations :
3519
 * <ul>
3520
 * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
3521
 * recommended to open a new dataset on the same underlying file.</li>
3522
 * <li>The returned dataset should only be accessed by one thread at a time. If
3523
 * you want to use it from different threads, you must add all necessary code
3524
 * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
3525
 * as GeoTIFF, maintain internal state variables that are updated each time a
3526
 * new block is read, thus preventing concurrent use.) </li>
3527
 * </ul>
3528
 *
3529
 * For drivers supporting the VSI virtual file API, it is possible to open a
3530
 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
3531
 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
3532
 * server (see VSIInstallCurlFileHandler())
3533
 *
3534
 * In order to reduce the need for searches through the operating system
3535
 * file system machinery, it is possible to give an optional list of files with
3536
 * the papszSiblingFiles parameter.
3537
 * This is the list of all files at the same level in the file system as the
3538
 * target file, including the target file. The filenames must not include any
3539
 * path components, are essentially just the output of VSIReadDir() on the
3540
 * parent directory. If the target object does not have filesystem semantics
3541
 * then the file list should be NULL.
3542
 *
3543
 * @param pszFilename the name of the file to access.  In the case of
3544
 * exotic drivers this may not refer to a physical file, but instead contain
3545
 * information for the driver on how to access a dataset.  It should be in UTF-8
3546
 * encoding.
3547
 *
3548
 * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
3549
 * through logical or operator.
3550
 * <ul>
3551
 * <li>Driver kind:
3552
 *   <ul>
3553
 *     <li>GDAL_OF_RASTER for raster drivers,</li>
3554
 *     <li>GDAL_OF_MULTIDIM_RASTER for multidimensional raster drivers,</li>
3555
 *     <li>GDAL_OF_VECTOR for vector drivers,</li>
3556
 *     <li>GDAL_OF_GNM for Geographic Network Model drivers.</li>
3557
 *    </ul>
3558
 * GDAL_OF_RASTER and GDAL_OF_MULTIDIM_RASTER are generally mutually
3559
 * exclusive. If none of the value is specified, GDAL_OF_RASTER | GDAL_OF_VECTOR
3560
 * | GDAL_OF_GNM is implied.
3561
 * </li>
3562
 * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.
3563
 * </li>
3564
 * <li>Shared mode: GDAL_OF_SHARED. If set,
3565
 * it allows the sharing of GDALDataset handles for a dataset with other callers
3566
 * that have set GDAL_OF_SHARED. In particular, GDALOpenEx() will first consult
3567
 * its list of currently open and shared GDALDataset's, and if the
3568
 * GetDescription() name for one exactly matches the pszFilename passed to
3569
 * GDALOpenEx() it will be referenced and returned, if GDALOpenEx() is called
3570
 * from the same thread.
3571
 * </li>
3572
 * <li>Thread safe mode: GDAL_OF_THREAD_SAFE (added in 3.10).
3573
 * This must be use in combination with GDAL_OF_RASTER, and is mutually
3574
 * exclusive with GDAL_OF_UPDATE, GDAL_OF_VECTOR, GDAL_OF_MULTIDIM_RASTER or
3575
 * GDAL_OF_GNM.
3576
 * </li>
3577
 * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set,
3578
 * a failed attempt to open the file will lead to an error message to be
3579
 * reported.
3580
 * </li>
3581
 * </ul>
3582
 *
3583
 * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
3584
 * terminated list of strings with the driver short names that must be
3585
 * considered.
3586
 *
3587
 * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
3588
 * options passed to candidate drivers. An option exists for all drivers,
3589
 * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
3590
 * The level index starts at 0. The level number can be suffixed by "only" to
3591
 * specify that only this overview level must be visible, and not sub-levels.
3592
 * Open options are validated by default, and a warning is emitted in case the
3593
 * option is not recognized. In some scenarios, it might be not desirable (e.g.
3594
 * when not knowing which driver will open the file), so the special open option
3595
 * VALIDATE_OPEN_OPTIONS can be set to NO to avoid such warnings. Alternatively,
3596
 * since GDAL 2.1, an option name can be preceded by the @ character to indicate
3597
 * that it may not cause a warning if the driver doesn't declare this option.
3598
 * Starting with GDAL 3.3, OVERVIEW_LEVEL=NONE is supported to indicate that
3599
 * no overviews should be exposed.
3600
 *
3601
 * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
3602
 * filenames that are auxiliary to the main filename. If NULL is passed, a
3603
 * probing of the file system will be done.
3604
 *
3605
 * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
3606
 * this handle can be cast to a GDALDataset *.
3607
 *
3608
 * @since GDAL 2.0
3609
 */
3610
3611
GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
3612
                                    unsigned int nOpenFlags,
3613
                                    const char *const *papszAllowedDrivers,
3614
                                    const char *const *papszOpenOptions,
3615
                                    const char *const *papszSiblingFiles)
3616
0
{
3617
0
    VALIDATE_POINTER1(pszFilename, "GDALOpen", nullptr);
3618
3619
    // Hack for the ZARR driver. We translate the CACHE_KERCHUNK_JSON
3620
    // into VSIKERCHUNK_USE_CACHE config option
3621
0
    std::unique_ptr<CPLConfigOptionSetter> poVSIKERCHUNK_USE_CACHESetter;
3622
0
    if (CPLFetchBool(papszOpenOptions, "CACHE_KERCHUNK_JSON", false))
3623
0
    {
3624
0
        poVSIKERCHUNK_USE_CACHESetter = std::make_unique<CPLConfigOptionSetter>(
3625
0
            "VSIKERCHUNK_USE_CACHE", "YES", false);
3626
0
    }
3627
3628
    // Do some sanity checks on incompatible flags with thread-safe mode.
3629
0
    if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3630
0
    {
3631
0
        const struct
3632
0
        {
3633
0
            int nFlag;
3634
0
            const char *pszFlagName;
3635
0
        } asFlags[] = {
3636
0
            {GDAL_OF_UPDATE, "GDAL_OF_UPDATE"},
3637
0
            {GDAL_OF_VECTOR, "GDAL_OF_VECTOR"},
3638
0
            {GDAL_OF_MULTIDIM_RASTER, "GDAL_OF_MULTIDIM_RASTER"},
3639
0
            {GDAL_OF_GNM, "GDAL_OF_GNM"},
3640
0
        };
3641
3642
0
        for (const auto &asFlag : asFlags)
3643
0
        {
3644
0
            if ((nOpenFlags & asFlag.nFlag) != 0)
3645
0
            {
3646
0
                CPLError(CE_Failure, CPLE_IllegalArg,
3647
0
                         "GDAL_OF_THREAD_SAFE and %s are mutually "
3648
0
                         "exclusive",
3649
0
                         asFlag.pszFlagName);
3650
0
                return nullptr;
3651
0
            }
3652
0
        }
3653
0
    }
3654
3655
    // If no driver kind is specified, assume all are to be probed.
3656
0
    if ((nOpenFlags & GDAL_OF_KIND_MASK) == 0)
3657
0
        nOpenFlags |= GDAL_OF_KIND_MASK & ~GDAL_OF_MULTIDIM_RASTER;
3658
3659
    /* -------------------------------------------------------------------- */
3660
    /*      In case of shared dataset, first scan the existing list to see  */
3661
    /*      if it could already contain the requested dataset.              */
3662
    /* -------------------------------------------------------------------- */
3663
0
    if (nOpenFlags & GDAL_OF_SHARED)
3664
0
    {
3665
0
        if (nOpenFlags & GDAL_OF_INTERNAL)
3666
0
        {
3667
0
            CPLError(CE_Failure, CPLE_IllegalArg,
3668
0
                     "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
3669
0
            return nullptr;
3670
0
        }
3671
3672
0
        auto poSharedDS =
3673
0
            GetSharedDS(pszFilename, nOpenFlags, papszOpenOptions);
3674
0
        if (poSharedDS)
3675
0
        {
3676
0
            poSharedDS->Reference();
3677
0
            return poSharedDS;
3678
0
        }
3679
0
    }
3680
3681
0
    GDALDriverManager *poDM = GetGDALDriverManager();
3682
    // CPLLocaleC  oLocaleForcer;
3683
3684
0
    CPLErrorReset();
3685
0
    VSIErrorReset();
3686
0
    CPLAssert(nullptr != poDM);
3687
3688
    // Build GDALOpenInfo just now to avoid useless file stat'ing if a
3689
    // shared dataset was asked before.
3690
0
    GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
3691
0
                           const_cast<char **>(papszSiblingFiles));
3692
0
    oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
3693
3694
0
    GDALAntiRecursionStruct &sAntiRecursion = GetAntiRecursionOpen();
3695
0
    if (sAntiRecursion.nRecLevel == 100)
3696
0
    {
3697
0
        CPLError(CE_Failure, CPLE_AppDefined,
3698
0
                 "GDALOpen() called with too many recursion levels");
3699
0
        return nullptr;
3700
0
    }
3701
3702
0
    std::string osAllowedDrivers;
3703
0
    for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
3704
0
        osAllowedDrivers += pszDriverName;
3705
0
    auto dsCtxt = GDALAntiRecursionStruct::DatasetContext(
3706
0
        std::string(pszFilename), nOpenFlags, osAllowedDrivers);
3707
0
    if (cpl::contains(sAntiRecursion.aosDatasetNamesWithFlags, dsCtxt))
3708
0
    {
3709
0
        CPLError(CE_Failure, CPLE_AppDefined,
3710
0
                 "GDALOpen() called on %s recursively", pszFilename);
3711
0
        return nullptr;
3712
0
    }
3713
3714
    // Remove leading @ if present.
3715
0
    char **papszOpenOptionsCleaned =
3716
0
        CSLDuplicate(const_cast<char **>(papszOpenOptions));
3717
0
    for (char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
3718
0
         ++papszIter)
3719
0
    {
3720
0
        char *pszOption = *papszIter;
3721
0
        if (pszOption[0] == '@')
3722
0
            memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
3723
0
    }
3724
3725
0
    oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3726
0
    oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN;
3727
3728
0
#ifdef OGRAPISPY_ENABLED
3729
0
    const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0;
3730
0
    const int iSnapshot =
3731
0
        (nOpenFlags & GDAL_OF_VECTOR) != 0 && (nOpenFlags & GDAL_OF_RASTER) == 0
3732
0
            ? OGRAPISpyOpenTakeSnapshot(pszFilename, bUpdate)
3733
0
            : INT_MIN;
3734
0
#endif
3735
3736
0
    const int nDriverCount = poDM->GetDriverCount(/*bIncludeHidden=*/true);
3737
0
    GDALDriver *poMissingPluginDriver = nullptr;
3738
0
    std::vector<GDALDriver *> apoSecondPassDrivers;
3739
3740
    // Lookup of matching driver for dataset can involve up to 2 passes:
3741
    // - in the first pass, all drivers that are compabile of the request mode
3742
    //   (raster/vector/etc.) are probed using their Identify() method if it
3743
    //   exists. If the Identify() method returns FALSE, the driver is skipped.
3744
    //   If the Identify() methods returns GDAL_IDENTIFY_UNKNOWN and that the
3745
    //   driver is a deferred-loading plugin, it is added to the
3746
    //   apoSecondPassDrivers list for potential later probing, and execution
3747
    //   continues to the next driver in the list.
3748
    //   Otherwise if Identify() returns non-FALSE, the Open() method is used.
3749
    //   If Open() returns a non-NULL dataset, the loop stops and it is
3750
    //   returned. Otherwise looping over remaining drivers continues.
3751
    // - the second pass is optional, only if at least one driver was added
3752
    //   into apoSecondPassDrivers during the first pass. It is similar
3753
    //   to the first pass except it runs only on apoSecondPassDrivers drivers.
3754
    //   And the Open() method of such drivers is used, causing them to be
3755
    //   loaded for real.
3756
0
    int iPass = 1;
3757
0
retry:
3758
0
    for (int iDriver = 0;
3759
0
         iDriver < (iPass == 1 ? nDriverCount
3760
0
                               : static_cast<int>(apoSecondPassDrivers.size()));
3761
0
         ++iDriver)
3762
0
    {
3763
0
        GDALDriver *poDriver =
3764
0
            iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
3765
0
                       : apoSecondPassDrivers[iDriver];
3766
0
        if (papszAllowedDrivers != nullptr &&
3767
0
            CSLFindString(papszAllowedDrivers,
3768
0
                          GDALGetDriverShortName(poDriver)) == -1)
3769
0
        {
3770
0
            continue;
3771
0
        }
3772
3773
0
        if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)
3774
0
            continue;
3775
3776
0
        if ((nOpenFlags & GDAL_OF_RASTER) != 0 &&
3777
0
            (nOpenFlags & GDAL_OF_VECTOR) == 0 &&
3778
0
            poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
3779
0
            continue;
3780
0
        if ((nOpenFlags & GDAL_OF_VECTOR) != 0 &&
3781
0
            (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3782
0
            poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
3783
0
            continue;
3784
0
        if ((nOpenFlags & GDAL_OF_MULTIDIM_RASTER) != 0 &&
3785
0
            (nOpenFlags & GDAL_OF_RASTER) == 0 &&
3786
0
            poDriver->GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) == nullptr)
3787
0
            continue;
3788
3789
        // Remove general OVERVIEW_LEVEL open options from list before passing
3790
        // it to the driver, if it isn't a driver specific option already.
3791
0
        char **papszTmpOpenOptions = nullptr;
3792
0
        char **papszTmpOpenOptionsToValidate = nullptr;
3793
0
        char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
3794
0
        if (CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
3795
0
                nullptr &&
3796
0
            !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3797
0
        {
3798
0
            papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
3799
0
            papszTmpOpenOptions =
3800
0
                CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", nullptr);
3801
0
            oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
3802
3803
0
            papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
3804
0
            papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate,
3805
0
                                                     "OVERVIEW_LEVEL", nullptr);
3806
0
            papszTmpOpenOptionsToValidate = papszOptionsToValidate;
3807
0
        }
3808
3809
0
        const int nIdentifyRes =
3810
0
            poDriver->pfnIdentifyEx
3811
0
                ? poDriver->pfnIdentifyEx(poDriver, &oOpenInfo)
3812
0
            : poDriver->pfnIdentify ? poDriver->pfnIdentify(&oOpenInfo)
3813
0
                                    : GDAL_IDENTIFY_UNKNOWN;
3814
0
        if (nIdentifyRes == FALSE)
3815
0
        {
3816
0
            CSLDestroy(papszTmpOpenOptions);
3817
0
            CSLDestroy(papszTmpOpenOptionsToValidate);
3818
0
            oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3819
0
            continue;
3820
0
        }
3821
0
        else if (iPass == 1 && nIdentifyRes < 0 &&
3822
0
                 poDriver->pfnOpen == nullptr &&
3823
0
                 poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
3824
0
        {
3825
            // Not loaded plugin
3826
0
            apoSecondPassDrivers.push_back(poDriver);
3827
0
            CSLDestroy(papszTmpOpenOptions);
3828
0
            CSLDestroy(papszTmpOpenOptionsToValidate);
3829
0
            oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3830
0
            continue;
3831
0
        }
3832
3833
0
        const bool bIdentifyRes = nIdentifyRes == GDAL_IDENTIFY_TRUE;
3834
0
        if (bIdentifyRes)
3835
0
        {
3836
0
            GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3837
0
        }
3838
3839
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3840
0
        const bool bFpAvailableBefore = oOpenInfo.fpL != nullptr;
3841
0
        CPLErrorReset();
3842
0
#endif
3843
3844
0
        sAntiRecursion.nRecLevel++;
3845
0
        sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);
3846
3847
0
        GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
3848
3849
0
        sAntiRecursion.nRecLevel--;
3850
0
        sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
3851
3852
0
        if (poDriver->pfnOpen != nullptr)
3853
0
        {
3854
            // If we couldn't determine for sure with Identify() (it returned
3855
            // -1), but Open() managed to open the file, post validate options.
3856
0
            if (poDS != nullptr &&
3857
0
                (poDriver->pfnIdentify || poDriver->pfnIdentifyEx) &&
3858
0
                !bIdentifyRes)
3859
0
            {
3860
0
                GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
3861
0
            }
3862
0
        }
3863
0
        else if (poDriver->pfnOpenWithDriverArg != nullptr)
3864
0
        {
3865
            // do nothing
3866
0
        }
3867
0
        else if (bIdentifyRes &&
3868
0
                 poDriver->GetMetadataItem("MISSING_PLUGIN_FILENAME"))
3869
0
        {
3870
0
            if (!poMissingPluginDriver)
3871
0
            {
3872
0
                poMissingPluginDriver = poDriver;
3873
0
            }
3874
0
        }
3875
0
        else
3876
0
        {
3877
            // should not happen given the GDAL_DCAP_OPEN check
3878
0
            CSLDestroy(papszTmpOpenOptions);
3879
0
            CSLDestroy(papszTmpOpenOptionsToValidate);
3880
0
            oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3881
0
            continue;
3882
0
        }
3883
3884
0
        CSLDestroy(papszTmpOpenOptions);
3885
0
        CSLDestroy(papszTmpOpenOptionsToValidate);
3886
0
        oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
3887
3888
0
        if (poDS != nullptr)
3889
0
        {
3890
0
            if (poDS->papszOpenOptions == nullptr)
3891
0
            {
3892
0
                poDS->papszOpenOptions = papszOpenOptionsCleaned;
3893
0
                papszOpenOptionsCleaned = nullptr;
3894
0
            }
3895
3896
            // Deal with generic OVERVIEW_LEVEL open option, unless it is
3897
            // driver specific.
3898
0
            if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
3899
0
                    nullptr &&
3900
0
                !poDriver->HasOpenOption("OVERVIEW_LEVEL"))
3901
0
            {
3902
0
                CPLString osVal(
3903
0
                    CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
3904
0
                const int nOvrLevel = EQUAL(osVal, "NONE") ? -1 : atoi(osVal);
3905
0
                const bool bThisLevelOnly =
3906
0
                    nOvrLevel == -1 || osVal.ifind("only") != std::string::npos;
3907
0
                GDALDataset *poOvrDS =
3908
0
                    GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly);
3909
0
                if (poOvrDS && (nOpenFlags & GDAL_OF_SHARED) != 0)
3910
0
                {
3911
0
                    if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3912
0
                    {
3913
0
                        CPLError(
3914
0
                            CE_Warning, CPLE_NotSupported,
3915
0
                            "A dataset opened by GDALOpenShared should have "
3916
0
                            "the same filename (%s) "
3917
0
                            "and description (%s)",
3918
0
                            pszFilename, poDS->GetDescription());
3919
0
                    }
3920
0
                    else
3921
0
                    {
3922
0
                        CSLDestroy(poDS->papszOpenOptions);
3923
0
                        poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3924
0
                        poDS->papszOpenOptions = CSLSetNameValue(
3925
0
                            poDS->papszOpenOptions, "OVERVIEW_LEVEL", nullptr);
3926
0
                    }
3927
0
                }
3928
0
                poDS->ReleaseRef();
3929
0
                poDS = poOvrDS;
3930
0
                if (poDS == nullptr)
3931
0
                {
3932
0
                    if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
3933
0
                    {
3934
0
                        CPLError(CE_Failure, CPLE_OpenFailed,
3935
0
                                 "Cannot open overview level %d of %s",
3936
0
                                 nOvrLevel, pszFilename);
3937
0
                    }
3938
0
                }
3939
0
                else
3940
0
                {
3941
                    // For thread-safe opening, currently poDS is what will be
3942
                    // the "master" dataset owned by the thread-safe dataset
3943
                    // returned to the user, hence we do not register it as a
3944
                    // visible one in the open dataset list, or mark it as shared.
3945
0
                    if (!(nOpenFlags & GDAL_OF_INTERNAL) &&
3946
0
                        !(nOpenFlags & GDAL_OF_THREAD_SAFE))
3947
0
                    {
3948
0
                        poDS->AddToDatasetOpenList();
3949
0
                    }
3950
0
                    if (nOpenFlags & GDAL_OF_SHARED)
3951
0
                    {
3952
0
                        CSLDestroy(poDS->papszOpenOptions);
3953
0
                        poDS->papszOpenOptions = CSLDuplicate(papszOpenOptions);
3954
0
                        poDS->nOpenFlags = nOpenFlags;
3955
0
                        if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
3956
0
                            poDS->MarkAsShared();
3957
0
                    }
3958
0
                }
3959
0
            }
3960
0
            else if (nOpenFlags & GDAL_OF_SHARED)
3961
0
            {
3962
0
                if (strcmp(pszFilename, poDS->GetDescription()) != 0)
3963
0
                {
3964
0
                    CPLError(CE_Warning, CPLE_NotSupported,
3965
0
                             "A dataset opened by GDALOpenShared should have "
3966
0
                             "the same filename (%s) "
3967
0
                             "and description (%s)",
3968
0
                             pszFilename, poDS->GetDescription());
3969
0
                }
3970
0
                else if (!(nOpenFlags & GDAL_OF_THREAD_SAFE))
3971
0
                {
3972
                    // For thread-safe opening, currently poDS is what will be
3973
                    // the "master" dataset owned by the thread-safe dataset
3974
                    // returned to the user, hence we do not or mark it as shared.
3975
0
                    poDS->MarkAsShared();
3976
0
                }
3977
0
            }
3978
3979
0
            VSIErrorReset();
3980
3981
0
            CSLDestroy(papszOpenOptionsCleaned);
3982
3983
0
#ifdef OGRAPISPY_ENABLED
3984
0
            if (iSnapshot != INT_MIN)
3985
0
            {
3986
0
                GDALDatasetH hDS = GDALDataset::ToHandle(poDS);
3987
0
                OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
3988
0
                poDS = GDALDataset::FromHandle(hDS);
3989
0
            }
3990
0
#endif
3991
3992
0
            if (poDS)
3993
0
            {
3994
0
                poDS->m_bCanBeReopened = true;
3995
3996
0
                if ((nOpenFlags & GDAL_OF_THREAD_SAFE) != 0)
3997
0
                {
3998
0
                    poDS =
3999
0
                        GDALGetThreadSafeDataset(
4000
0
                            std::unique_ptr<GDALDataset>(poDS), GDAL_OF_RASTER)
4001
0
                            .release();
4002
0
                    if (poDS)
4003
0
                    {
4004
0
                        poDS->m_bCanBeReopened = true;
4005
0
                        poDS->poDriver = poDriver;
4006
0
                        poDS->nOpenFlags = nOpenFlags;
4007
0
                        if (!(nOpenFlags & GDAL_OF_INTERNAL))
4008
0
                            poDS->AddToDatasetOpenList();
4009
0
                        if (nOpenFlags & GDAL_OF_SHARED)
4010
0
                            poDS->MarkAsShared();
4011
0
                    }
4012
0
                }
4013
0
            }
4014
4015
0
            return poDS;
4016
0
        }
4017
4018
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4019
0
        if (bFpAvailableBefore && oOpenInfo.fpL == nullptr)
4020
0
        {
4021
            // In case the file descriptor was "consumed" by a driver
4022
            // that ultimately failed, re-open it for next drivers.
4023
0
            oOpenInfo.fpL = VSIFOpenL(
4024
0
                pszFilename, (oOpenInfo.eAccess == GA_Update) ? "r+b" : "rb");
4025
0
        }
4026
#else
4027
        if (CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
4028
        {
4029
            CSLDestroy(papszOpenOptionsCleaned);
4030
4031
#ifdef OGRAPISPY_ENABLED
4032
            if (iSnapshot != INT_MIN)
4033
            {
4034
                GDALDatasetH hDS = nullptr;
4035
                OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4036
            }
4037
#endif
4038
            return nullptr;
4039
        }
4040
#endif
4041
0
    }
4042
4043
    // cppcheck-suppress knownConditionTrueFalse
4044
0
    if (iPass == 1 && !apoSecondPassDrivers.empty())
4045
0
    {
4046
0
        CPLDebugOnly("GDAL", "GDALOpen(): Second pass");
4047
0
        iPass = 2;
4048
0
        goto retry;
4049
0
    }
4050
4051
0
    CSLDestroy(papszOpenOptionsCleaned);
4052
4053
0
#ifdef OGRAPISPY_ENABLED
4054
0
    if (iSnapshot != INT_MIN)
4055
0
    {
4056
0
        GDALDatasetH hDS = nullptr;
4057
0
        OGRAPISpyOpen(pszFilename, bUpdate, iSnapshot, &hDS);
4058
0
    }
4059
0
#endif
4060
4061
0
    if (nOpenFlags & GDAL_OF_VERBOSE_ERROR)
4062
0
    {
4063
0
        if (nDriverCount == 0)
4064
0
        {
4065
0
            CPLError(CE_Failure, CPLE_OpenFailed, "No driver registered.");
4066
0
        }
4067
0
        else if (poMissingPluginDriver)
4068
0
        {
4069
0
            std::string osMsg("`");
4070
0
            osMsg += pszFilename;
4071
0
            osMsg += "' not recognized as being in a supported file format. "
4072
0
                     "It could have been recognized by driver ";
4073
0
            osMsg += poMissingPluginDriver->GetDescription();
4074
0
            osMsg += ", but plugin ";
4075
0
            osMsg +=
4076
0
                GDALGetMessageAboutMissingPluginDriver(poMissingPluginDriver);
4077
4078
0
            CPLError(CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str());
4079
0
        }
4080
        // Check to see if there was a filesystem error, and report it if so.
4081
        // If not, return a more generic error.
4082
0
        else if (!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
4083
0
        {
4084
0
            if (oOpenInfo.bStatOK)
4085
0
            {
4086
0
                CPLError(CE_Failure, CPLE_OpenFailed,
4087
0
                         "`%s' not recognized as being in a supported file "
4088
0
                         "format.",
4089
0
                         pszFilename);
4090
0
            }
4091
0
            else
4092
0
            {
4093
                // If Stat failed and no VSI error was set, assume it is because
4094
                // the file did not exist on the filesystem.
4095
0
                CPLError(CE_Failure, CPLE_OpenFailed,
4096
0
                         "`%s' does not exist in the file system, "
4097
0
                         "and is not recognized as a supported dataset name.",
4098
0
                         pszFilename);
4099
0
            }
4100
0
        }
4101
0
    }
4102
4103
0
    return nullptr;
4104
0
}
4105
4106
/************************************************************************/
4107
/*                           GDALOpenShared()                           */
4108
/************************************************************************/
4109
4110
/**
4111
 * \brief Open a raster file as a GDALDataset.
4112
 *
4113
 * This function works the same as GDALOpen(), but allows the sharing of
4114
 * GDALDataset handles for a dataset with other callers to GDALOpenShared().
4115
 *
4116
 * In particular, GDALOpenShared() will first consult its list of currently
4117
 * open and shared GDALDataset's, and if the GetDescription() name for one
4118
 * exactly matches the pszFilename passed to GDALOpenShared() it will be
4119
 * referenced and returned.
4120
 *
4121
 * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
4122
 * pszFilename from two different threads, a different GDALDataset object will
4123
 * be returned as it is not safe to use the same dataset from different threads,
4124
 * unless the user does explicitly use mutexes in its code.
4125
 *
4126
 * For drivers supporting the VSI virtual file API, it is possible to open a
4127
 * file in a .zip archive (see VSIInstallZipFileHandler()), in a
4128
 * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
4129
 * server (see VSIInstallCurlFileHandler())
4130
 *
4131
 * \sa GDALOpen()
4132
 * \sa GDALOpenEx()
4133
 *
4134
 * @param pszFilename the name of the file to access.  In the case of
4135
 * exotic drivers this may not refer to a physical file, but instead contain
4136
 * information for the driver on how to access a dataset.  It should be in
4137
 * UTF-8 encoding.
4138
 *
4139
 * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
4140
 * drivers support only read only access.
4141
 *
4142
 * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
4143
 * this handle can be cast to a GDALDataset *.
4144
 */
4145
4146
GDALDatasetH CPL_STDCALL GDALOpenShared(const char *pszFilename,
4147
                                        GDALAccess eAccess)
4148
0
{
4149
0
    VALIDATE_POINTER1(pszFilename, "GDALOpenShared", nullptr);
4150
0
    return GDALOpenEx(pszFilename,
4151
0
                      GDAL_OF_RASTER |
4152
0
                          (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
4153
0
                          GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
4154
0
                      nullptr, nullptr, nullptr);
4155
0
}
4156
4157
/************************************************************************/
4158
/*                             GDALClose()                              */
4159
/************************************************************************/
4160
4161
/**
4162
 * \brief Close GDAL dataset.
4163
 *
4164
 * For non-shared datasets (opened with GDALOpen()) the dataset is closed
4165
 * using the C++ "delete" operator, recovering all dataset related resources.
4166
 * For shared datasets (opened with GDALOpenShared()) the dataset is
4167
 * dereferenced, and closed only if the referenced count has dropped below 1.
4168
 *
4169
 * @param hDS The dataset to close.  May be cast from a "GDALDataset *".
4170
 * @return CE_None in case of success (return value since GDAL 3.7). On a
4171
 * shared dataset whose reference count is not dropped below 1, CE_None will
4172
 * be returned.
4173
 */
4174
4175
CPLErr CPL_STDCALL GDALClose(GDALDatasetH hDS)
4176
4177
0
{
4178
0
    if (!hDS)
4179
0
        return CE_None;
4180
4181
0
#ifdef OGRAPISPY_ENABLED
4182
0
    if (bOGRAPISpyEnabled)
4183
0
        OGRAPISpyPreClose(hDS);
4184
0
#endif
4185
4186
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
4187
4188
0
    if (poDS->GetShared())
4189
0
    {
4190
        /* --------------------------------------------------------------------
4191
         */
4192
        /*      If this file is in the shared dataset list then dereference */
4193
        /*      it, and only delete/remote it if the reference count has */
4194
        /*      dropped to zero. */
4195
        /* --------------------------------------------------------------------
4196
         */
4197
0
        if (poDS->Dereference() > 0)
4198
0
            return CE_None;
4199
4200
0
        CPLErr eErr = poDS->Close();
4201
0
        delete poDS;
4202
4203
0
#ifdef OGRAPISPY_ENABLED
4204
0
        if (bOGRAPISpyEnabled)
4205
0
            OGRAPISpyPostClose();
4206
0
#endif
4207
4208
0
        return eErr;
4209
0
    }
4210
4211
    /* -------------------------------------------------------------------- */
4212
    /*      This is not shared dataset, so directly delete it.              */
4213
    /* -------------------------------------------------------------------- */
4214
0
    CPLErr eErr = poDS->Close();
4215
0
    delete poDS;
4216
4217
0
#ifdef OGRAPISPY_ENABLED
4218
0
    if (bOGRAPISpyEnabled)
4219
0
        OGRAPISpyPostClose();
4220
0
#endif
4221
0
    return eErr;
4222
0
}
4223
4224
/************************************************************************/
4225
/*                        GDALDumpOpenDataset()                         */
4226
/************************************************************************/
4227
4228
static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
4229
0
{
4230
0
    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
4231
0
    FILE *fp = static_cast<FILE *>(user_data);
4232
0
    GDALDataset *poDS = psStruct->poDS;
4233
4234
0
    const char *pszDriverName = poDS->GetDriver() == nullptr
4235
0
                                    ? "DriverIsNULL"
4236
0
                                    : poDS->GetDriver()->GetDescription();
4237
4238
0
    poDS->Reference();
4239
0
    CPL_IGNORE_RET_VAL(
4240
0
        VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4241
0
                   poDS->GetShared() ? 'S' : 'N', pszDriverName,
4242
0
                   static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
4243
0
                   poDS->GetRasterYSize(), poDS->GetRasterCount(),
4244
0
                   poDS->GetDescription()));
4245
4246
0
    return TRUE;
4247
0
}
4248
4249
static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
4250
0
{
4251
4252
    // Don't list shared datasets. They have already been listed by
4253
    // GDALDumpOpenSharedDatasetsForeach.
4254
0
    if (poDS->GetShared())
4255
0
        return TRUE;
4256
4257
0
    const char *pszDriverName = poDS->GetDriver() == nullptr
4258
0
                                    ? "DriverIsNULL"
4259
0
                                    : poDS->GetDriver()->GetDescription();
4260
4261
0
    poDS->Reference();
4262
0
    CPL_IGNORE_RET_VAL(
4263
0
        VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
4264
0
                   poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
4265
0
                   poDS->GetRasterXSize(), poDS->GetRasterYSize(),
4266
0
                   poDS->GetRasterCount(), poDS->GetDescription()));
4267
4268
0
    return TRUE;
4269
0
}
4270
4271
/**
4272
 * \brief List open datasets.
4273
 *
4274
 * Dumps a list of all open datasets (shared or not) to the indicated
4275
 * text file (may be stdout or stderr).   This function is primarily intended
4276
 * to assist in debugging "dataset leaks" and reference counting issues.
4277
 * The information reported includes the dataset name, referenced count,
4278
 * shared status, driver name, size, and band count.
4279
 */
4280
4281
int CPL_STDCALL GDALDumpOpenDatasets(FILE *fp)
4282
4283
0
{
4284
0
    VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
4285
4286
0
    CPLMutexHolderD(&hDLMutex);
4287
4288
0
    if (poAllDatasetMap == nullptr)
4289
0
        return 0;
4290
4291
0
    CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
4292
4293
0
    for (const auto &oIter : *poAllDatasetMap)
4294
0
    {
4295
0
        GDALDumpOpenDatasetsForeach(oIter.first, fp);
4296
0
    }
4297
4298
0
    if (phSharedDatasetSet != nullptr)
4299
0
    {
4300
0
        CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach,
4301
0
                          fp);
4302
0
    }
4303
0
    return static_cast<int>(poAllDatasetMap->size());
4304
0
}
4305
4306
/************************************************************************/
4307
/*                        BeginAsyncReader()                            */
4308
/************************************************************************/
4309
4310
/**
4311
 * \brief Sets up an asynchronous data request
4312
 *
4313
 * This method establish an asynchronous raster read request for the
4314
 * indicated window on the dataset into the indicated buffer.  The parameters
4315
 * for windowing, buffer size, buffer type and buffer organization are similar
4316
 * to those for GDALDataset::RasterIO(); however, this call only launches
4317
 * the request and filling the buffer is accomplished via calls to
4318
 * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4319
 *
4320
 * Once all processing for the created session is complete, or if no further
4321
 * refinement of the request is required, the GDALAsyncReader object should
4322
 * be destroyed with the GDALDataset::EndAsyncReader() method.
4323
 *
4324
 * Note that the data buffer (pData) will potentially continue to be
4325
 * updated as long as the session lives, but it is not deallocated when
4326
 * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
4327
 * should be deallocated by the application at that point.
4328
 *
4329
 * Additional information on asynchronous IO in GDAL may be found at:
4330
 *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4331
 *
4332
 * This method is the same as the C GDALBeginAsyncReader() function.
4333
 *
4334
 * @param nXOff The pixel offset to the top left corner of the region
4335
 * of the band to be accessed.  This would be zero to start from the left side.
4336
 *
4337
 * @param nYOff The line offset to the top left corner of the region
4338
 * of the band to be accessed.  This would be zero to start from the top.
4339
 *
4340
 * @param nXSize The width of the region of the band to be accessed in pixels.
4341
 *
4342
 * @param nYSize The height of the region of the band to be accessed in lines.
4343
 *
4344
 * @param pBuf The buffer into which the data should be read. This buffer must
4345
 * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4346
 * It is organized in left to right,top to bottom pixel order.  Spacing is
4347
 * controlled by the nPixelSpace, and nLineSpace parameters.
4348
 *
4349
 * @param nBufXSize the width of the buffer image into which the desired region
4350
 * is to be read, or from which it is to be written.
4351
 *
4352
 * @param nBufYSize the height of the buffer image into which the desired
4353
 * region is to be read, or from which it is to be written.
4354
 *
4355
 * @param eBufType the type of the pixel values in the pData data buffer.  The
4356
 * pixel values will automatically be translated to/from the GDALRasterBand
4357
 * data type as needed.
4358
 *
4359
 * @param nBandCount the number of bands being read or written.
4360
 *
4361
 * @param panBandMap the list of nBandCount band numbers being read/written.
4362
 * Note band numbers are 1 based.   This may be NULL to select the first
4363
 * nBandCount bands.
4364
 *
4365
 * @param nPixelSpace The byte offset from the start of one pixel value in
4366
 * pData to the start of the next pixel value within a scanline.  If defaulted
4367
 * (0) the size of the datatype eBufType is used.
4368
 *
4369
 * @param nLineSpace The byte offset from the start of one scanline in
4370
 * pData to the start of the next.  If defaulted the size of the datatype
4371
 * eBufType * nBufXSize is used.
4372
 *
4373
 * @param nBandSpace the byte offset from the start of one bands data to the
4374
 * start of the next.  If defaulted (zero) the value will be
4375
 * nLineSpace * nBufYSize implying band sequential organization
4376
 * of the data buffer.
4377
 *
4378
 * @param papszOptions Driver specific control options in a string list or NULL.
4379
 * Consult driver documentation for options supported.
4380
 *
4381
 * @return The GDALAsyncReader object representing the request.
4382
 */
4383
4384
GDALAsyncReader *GDALDataset::BeginAsyncReader(
4385
    int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
4386
    int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
4387
    int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions)
4388
0
{
4389
    // See gdaldefaultasync.cpp
4390
4391
0
    return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
4392
0
                                     nBufXSize, nBufYSize, eBufType, nBandCount,
4393
0
                                     panBandMap, nPixelSpace, nLineSpace,
4394
0
                                     nBandSpace, papszOptions);
4395
0
}
4396
4397
/************************************************************************/
4398
/*                        GDALBeginAsyncReader()                      */
4399
/************************************************************************/
4400
4401
/**
4402
 * \brief Sets up an asynchronous data request
4403
 *
4404
 * This method establish an asynchronous raster read request for the
4405
 * indicated window on the dataset into the indicated buffer.  The parameters
4406
 * for windowing, buffer size, buffer type and buffer organization are similar
4407
 * to those for GDALDataset::RasterIO(); however, this call only launches
4408
 * the request and filling the buffer is accomplished via calls to
4409
 * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
4410
 *
4411
 * Once all processing for the created session is complete, or if no further
4412
 * refinement of the request is required, the GDALAsyncReader object should
4413
 * be destroyed with the GDALDataset::EndAsyncReader() method.
4414
 *
4415
 * Note that the data buffer (pData) will potentially continue to be
4416
 * updated as long as the session lives, but it is not deallocated when
4417
 * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
4418
 * should be deallocated by the application at that point.
4419
 *
4420
 * Additional information on asynchronous IO in GDAL may be found at:
4421
 *   https://gdal.org/development/rfc/rfc24_progressive_data_support.html
4422
 *
4423
 * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
4424
 *
4425
 * @param hDS handle to the dataset object.
4426
 *
4427
 * @param nXOff The pixel offset to the top left corner of the region
4428
 * of the band to be accessed.  This would be zero to start from the left side.
4429
 *
4430
 * @param nYOff The line offset to the top left corner of the region
4431
 * of the band to be accessed.  This would be zero to start from the top.
4432
 *
4433
 * @param nXSize The width of the region of the band to be accessed in pixels.
4434
 *
4435
 * @param nYSize The height of the region of the band to be accessed in lines.
4436
 *
4437
 * @param pBuf The buffer into which the data should be read. This buffer must
4438
 * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
4439
 * It is organized in left to right,top to bottom pixel order.  Spacing is
4440
 * controlled by the nPixelSpace, and nLineSpace parameters.
4441
 *
4442
 * @param nBufXSize the width of the buffer image into which the desired region
4443
 * is to be read, or from which it is to be written.
4444
 *
4445
 * @param nBufYSize the height of the buffer image into which the desired
4446
 * region is to be read, or from which it is to be written.
4447
 *
4448
 * @param eBufType the type of the pixel values in the pData data buffer.  The
4449
 * pixel values will automatically be translated to/from the GDALRasterBand
4450
 * data type as needed.
4451
 *
4452
 * @param nBandCount the number of bands being read or written.
4453
 *
4454
 * @param panBandMap the list of nBandCount band numbers being read/written.
4455
 * Note band numbers are 1 based.   This may be NULL to select the first
4456
 * nBandCount bands.
4457
 *
4458
 * @param nPixelSpace The byte offset from the start of one pixel value in
4459
 * pData to the start of the next pixel value within a scanline.  If defaulted
4460
 * (0) the size of the datatype eBufType is used.
4461
 *
4462
 * @param nLineSpace The byte offset from the start of one scanline in
4463
 * pData to the start of the next.  If defaulted the size of the datatype
4464
 * eBufType * nBufXSize is used.
4465
 *
4466
 * @param nBandSpace the byte offset from the start of one bands data to the
4467
 * start of the next.  If defaulted (zero) the value will be
4468
 * nLineSpace * nBufYSize implying band sequential organization
4469
 * of the data buffer.
4470
 *
4471
 * @param papszOptions Driver specific control options in a string list or NULL.
4472
 * Consult driver documentation for options supported.
4473
 *
4474
 * @return handle representing the request.
4475
 */
4476
4477
GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(
4478
    GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf,
4479
    int nBufXSize, int nBufYSize, GDALDataType eBufType, int nBandCount,
4480
    int *panBandMap, int nPixelSpace, int nLineSpace, int nBandSpace,
4481
    CSLConstList papszOptions)
4482
4483
0
{
4484
0
    VALIDATE_POINTER1(hDS, "GDALDataset", nullptr);
4485
0
    return static_cast<GDALAsyncReaderH>(
4486
0
        GDALDataset::FromHandle(hDS)->BeginAsyncReader(
4487
0
            nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
4488
0
            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
4489
0
            const_cast<char **>(papszOptions)));
4490
0
}
4491
4492
/************************************************************************/
4493
/*                        EndAsyncReader()                            */
4494
/************************************************************************/
4495
4496
/**
4497
 * End asynchronous request.
4498
 *
4499
 * This method destroys an asynchronous io request and recovers all
4500
 * resources associated with it.
4501
 *
4502
 * This method is the same as the C function GDALEndAsyncReader().
4503
 *
4504
 * @param poARIO pointer to a GDALAsyncReader
4505
 */
4506
4507
void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO)
4508
0
{
4509
0
    delete poARIO;
4510
0
}
4511
4512
/************************************************************************/
4513
/*                        GDALEndAsyncReader()                        */
4514
/************************************************************************/
4515
4516
/**
4517
 * End asynchronous request.
4518
 *
4519
 * This method destroys an asynchronous io request and recovers all
4520
 * resources associated with it.
4521
 *
4522
 * This method is the same as the C++ method GDALDataset::EndAsyncReader().
4523
 *
4524
 * @param hDS handle to the dataset object.
4525
 * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
4526
 */
4527
4528
void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS,
4529
                                    GDALAsyncReaderH hAsyncReaderH)
4530
0
{
4531
0
    VALIDATE_POINTER0(hDS, "GDALDataset");
4532
0
    VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
4533
0
    GDALDataset::FromHandle(hDS)->EndAsyncReader(
4534
0
        static_cast<GDALAsyncReader *>(hAsyncReaderH));
4535
0
}
4536
4537
/************************************************************************/
4538
/*                       CloseDependentDatasets()                       */
4539
/************************************************************************/
4540
4541
/**
4542
 * Drop references to any other datasets referenced by this dataset.
4543
 *
4544
 * This method should release any reference to other datasets (e.g. a VRT
4545
 * dataset to its sources), but not close the current dataset itself.
4546
 *
4547
 * If at least, one reference to a dependent dataset has been dropped,
4548
 * this method should return TRUE. Otherwise it *should* return FALSE.
4549
 * (Failure to return the proper value might result in infinite loop)
4550
 *
4551
 * This method can be called several times on a given dataset. After
4552
 * the first time, it should not do anything and return FALSE.
4553
 *
4554
 * The driver implementation may choose to destroy its raster bands,
4555
 * so be careful not to call any method on the raster bands afterwards.
4556
 *
4557
 * Basically the only safe action you can do after calling
4558
 * CloseDependentDatasets() is to call the destructor.
4559
 *
4560
 * Note: the only legitimate caller of CloseDependentDatasets() is
4561
 * GDALDriverManager::~GDALDriverManager()
4562
 *
4563
 * @return TRUE if at least one reference to another dataset has been dropped.
4564
 */
4565
int GDALDataset::CloseDependentDatasets()
4566
0
{
4567
0
    return oOvManager.CloseDependentDatasets();
4568
0
}
4569
4570
/************************************************************************/
4571
/*                            ReportError()                             */
4572
/************************************************************************/
4573
4574
#ifndef DOXYGEN_XML
4575
/**
4576
 * \brief Emits an error related to a dataset.
4577
 *
4578
 * This function is a wrapper for regular CPLError(). The only difference
4579
 * with CPLError() is that it prepends the error message with the dataset
4580
 * name.
4581
 *
4582
 * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4583
 * @param err_no the error number (CPLE_*) from cpl_error.h.
4584
 * @param fmt a printf() style format string.  Any additional arguments
4585
 * will be treated as arguments to fill in this format in a manner
4586
 * similar to printf().
4587
 *
4588
 * @since GDAL 1.9.0
4589
 */
4590
4591
void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
4592
                              const char *fmt, ...) const
4593
0
{
4594
0
    va_list args;
4595
0
    va_start(args, fmt);
4596
0
    ReportErrorV(GetDescription(), eErrClass, err_no, fmt, args);
4597
0
    va_end(args);
4598
0
}
4599
4600
/**
4601
 * \brief Emits an error related to a dataset (static method)
4602
 *
4603
 * This function is a wrapper for regular CPLError(). The only difference
4604
 * with CPLError() is that it prepends the error message with the dataset
4605
 * name.
4606
 *
4607
 * @param pszDSName dataset name.
4608
 * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
4609
 * @param err_no the error number (CPLE_*) from cpl_error.h.
4610
 * @param fmt a printf() style format string.  Any additional arguments
4611
 * will be treated as arguments to fill in this format in a manner
4612
 * similar to printf().
4613
 *
4614
 * @since GDAL 3.2.0
4615
 */
4616
4617
void GDALDataset::ReportError(const char *pszDSName, CPLErr eErrClass,
4618
                              CPLErrorNum err_no, const char *fmt, ...)
4619
0
{
4620
0
    va_list args;
4621
0
    va_start(args, fmt);
4622
0
    ReportErrorV(pszDSName, eErrClass, err_no, fmt, args);
4623
0
    va_end(args);
4624
0
}
4625
4626
void GDALDataset::ReportErrorV(const char *pszDSName, CPLErr eErrClass,
4627
                               CPLErrorNum err_no, const char *fmt,
4628
                               va_list args)
4629
0
{
4630
0
    pszDSName = CPLGetFilename(pszDSName);
4631
0
    if (pszDSName[0] != '\0')
4632
0
    {
4633
0
        CPLError(eErrClass, err_no, "%s",
4634
0
                 std::string(pszDSName)
4635
0
                     .append(": ")
4636
0
                     .append(CPLString().vPrintf(fmt, args))
4637
0
                     .c_str());
4638
0
    }
4639
0
    else
4640
0
    {
4641
0
        CPLErrorV(eErrClass, err_no, fmt, args);
4642
0
    }
4643
0
}
4644
#endif
4645
4646
/************************************************************************/
4647
/*                            GetMetadata()                             */
4648
/************************************************************************/
4649
char **GDALDataset::GetMetadata(const char *pszDomain)
4650
0
{
4651
#ifndef WITHOUT_DERIVED
4652
    if (pszDomain != nullptr && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
4653
    {
4654
        oDerivedMetadataList.Clear();
4655
4656
        // First condition: at least one raster band.
4657
        if (GetRasterCount() > 0)
4658
        {
4659
            // Check if there is at least one complex band.
4660
            bool hasAComplexBand = false;
4661
4662
            for (int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
4663
            {
4664
                if (GDALDataTypeIsComplex(
4665
                        GetRasterBand(rasterId)->GetRasterDataType()))
4666
                {
4667
                    hasAComplexBand = true;
4668
                    break;
4669
                }
4670
            }
4671
4672
            unsigned int nbSupportedDerivedDS = 0;
4673
            const DerivedDatasetDescription *poDDSDesc =
4674
                GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
4675
4676
            int nNumDataset = 1;
4677
            for (unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
4678
                 ++derivedId)
4679
            {
4680
                if (hasAComplexBand ||
4681
                    CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
4682
                        "complex")
4683
                {
4684
                    oDerivedMetadataList.SetNameValue(
4685
                        CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
4686
                        CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
4687
                                   poDDSDesc[derivedId].pszDatasetName,
4688
                                   GetDescription()));
4689
4690
                    CPLString osDesc(
4691
                        CPLSPrintf("%s from %s",
4692
                                   poDDSDesc[derivedId].pszDatasetDescription,
4693
                                   GetDescription()));
4694
                    oDerivedMetadataList.SetNameValue(
4695
                        CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
4696
                        osDesc.c_str());
4697
4698
                    nNumDataset++;
4699
                }
4700
            }
4701
        }
4702
        return oDerivedMetadataList.List();
4703
    }
4704
#endif
4705
4706
0
    return GDALMajorObject::GetMetadata(pszDomain);
4707
0
}
4708
4709
// clang-format off
4710
4711
/**
4712
 * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
4713
 * \brief Set metadata.
4714
 *
4715
 * CAUTION: depending on the format, older values of the updated information
4716
 * might still be found in the file in a "ghost" state, even if no longer
4717
 * accessible through the GDAL API. This is for example the case of the GTiff
4718
 * format (this is not a exhaustive list)
4719
 *
4720
 * The C function GDALSetMetadata() does the same thing as this method.
4721
 *
4722
 * @param papszMetadata the metadata in name=value string list format to
4723
 * apply.
4724
 * @param pszDomain the domain of interest.  Use "" or NULL for the default
4725
 * domain.
4726
 * @return CE_None on success, CE_Failure on failure and CE_Warning if the
4727
 * metadata has been accepted, but is likely not maintained persistently
4728
 * by the underlying object between sessions.
4729
 */
4730
4731
/**
4732
 * \fn GDALDataset::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
4733
 * \brief Set single metadata item.
4734
 *
4735
 * CAUTION: depending on the format, older values of the updated information
4736
 * might still be found in the file in a "ghost" state, even if no longer
4737
 * accessible through the GDAL API. This is for example the case of the GTiff
4738
 * format (this is not a exhaustive list)
4739
 *
4740
 * The C function GDALSetMetadataItem() does the same thing as this method.
4741
 *
4742
 * @param pszName the key for the metadata item to fetch.
4743
 * @param pszValue the value to assign to the key.
4744
 * @param pszDomain the domain to set within, use NULL for the default domain.
4745
 *
4746
 * @return CE_None on success, or an error code on failure.
4747
 */
4748
4749
// clang-format on
4750
4751
/************************************************************************/
4752
/*                            GetMetadataDomainList()                   */
4753
/************************************************************************/
4754
4755
char **GDALDataset::GetMetadataDomainList()
4756
0
{
4757
0
    char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
4758
4759
    // Ensure that we do not duplicate DERIVED domain.
4760
0
    if (GetRasterCount() > 0 &&
4761
0
        CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
4762
0
    {
4763
0
        currentDomainList =
4764
0
            CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
4765
0
    }
4766
0
    return currentDomainList;
4767
0
}
4768
4769
/************************************************************************/
4770
/*                            GetDriverName()                           */
4771
/************************************************************************/
4772
4773
/** Return driver name.
4774
 * @return driver name.
4775
 */
4776
const char *GDALDataset::GetDriverName()
4777
0
{
4778
0
    if (poDriver)
4779
0
        return poDriver->GetDescription();
4780
0
    return "";
4781
0
}
4782
4783
/************************************************************************/
4784
/*                     GDALDatasetReleaseResultSet()                    */
4785
/************************************************************************/
4786
4787
/**
4788
 \brief Release results of ExecuteSQL().
4789
4790
 This function should only be used to deallocate OGRLayers resulting from
4791
 an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
4792
 results set before destroying the GDALDataset may cause errors.
4793
4794
 This function is the same as the C++ method GDALDataset::ReleaseResultSet()
4795
4796
 @since GDAL 2.0
4797
4798
 @param hDS the dataset handle.
4799
 @param hLayer the result of a previous ExecuteSQL() call.
4800
4801
*/
4802
void GDALDatasetReleaseResultSet(GDALDatasetH hDS, OGRLayerH hLayer)
4803
4804
0
{
4805
0
    VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
4806
4807
0
#ifdef OGRAPISPY_ENABLED
4808
0
    if (bOGRAPISpyEnabled)
4809
0
        OGRAPISpy_DS_ReleaseResultSet(hDS, hLayer);
4810
0
#endif
4811
4812
0
    GDALDataset::FromHandle(hDS)->ReleaseResultSet(
4813
0
        OGRLayer::FromHandle(hLayer));
4814
0
}
4815
4816
/************************************************************************/
4817
/*                       GDALDatasetGetLayerCount()                     */
4818
/************************************************************************/
4819
4820
/**
4821
 \brief Get the number of layers in this dataset.
4822
4823
 This function is the same as the C++ method GDALDataset::GetLayerCount()
4824
4825
 @since GDAL 2.0
4826
4827
 @param hDS the dataset handle.
4828
 @return layer count.
4829
*/
4830
4831
int GDALDatasetGetLayerCount(GDALDatasetH hDS)
4832
4833
0
{
4834
0
    VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
4835
4836
0
#ifdef OGRAPISPY_ENABLED
4837
0
    if (bOGRAPISpyEnabled)
4838
0
        OGRAPISpy_DS_GetLayerCount(reinterpret_cast<GDALDatasetH>(hDS));
4839
0
#endif
4840
4841
0
    return GDALDataset::FromHandle(hDS)->GetLayerCount();
4842
0
}
4843
4844
/************************************************************************/
4845
/*                        GDALDatasetGetLayer()                         */
4846
/************************************************************************/
4847
4848
/**
4849
 \brief Fetch a layer by index.
4850
4851
 The returned layer remains owned by the
4852
 GDALDataset and should not be deleted by the application.
4853
4854
 This function is the same as the C++ method GDALDataset::GetLayer()
4855
4856
 @since GDAL 2.0
4857
4858
 @param hDS the dataset handle.
4859
 @param iLayer a layer number between 0 and GetLayerCount()-1.
4860
4861
 @return the layer, or NULL if iLayer is out of range or an error occurs.
4862
*/
4863
4864
OGRLayerH GDALDatasetGetLayer(GDALDatasetH hDS, int iLayer)
4865
4866
0
{
4867
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", nullptr);
4868
4869
0
    OGRLayerH hLayer =
4870
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->GetLayer(iLayer));
4871
4872
0
#ifdef OGRAPISPY_ENABLED
4873
0
    if (bOGRAPISpyEnabled)
4874
0
        OGRAPISpy_DS_GetLayer(hDS, iLayer, hLayer);
4875
0
#endif
4876
4877
0
    return hLayer;
4878
0
}
4879
4880
/************************************************************************/
4881
/*                     GDALDatasetGetLayerByName()                      */
4882
/************************************************************************/
4883
4884
/**
4885
 \brief Fetch a layer by name.
4886
4887
 The returned layer remains owned by the
4888
 GDALDataset and should not be deleted by the application.
4889
4890
 This function is the same as the C++ method GDALDataset::GetLayerByName()
4891
4892
 @since GDAL 2.0
4893
4894
 @param hDS the dataset handle.
4895
 @param pszName the layer name of the layer to fetch.
4896
4897
 @return the layer, or NULL if Layer is not found or an error occurs.
4898
*/
4899
4900
OGRLayerH GDALDatasetGetLayerByName(GDALDatasetH hDS, const char *pszName)
4901
4902
0
{
4903
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", nullptr);
4904
4905
0
    OGRLayerH hLayer = OGRLayer::ToHandle(
4906
0
        GDALDataset::FromHandle(hDS)->GetLayerByName(pszName));
4907
4908
0
#ifdef OGRAPISPY_ENABLED
4909
0
    if (bOGRAPISpyEnabled)
4910
0
        OGRAPISpy_DS_GetLayerByName(hDS, pszName, hLayer);
4911
0
#endif
4912
4913
0
    return hLayer;
4914
0
}
4915
4916
/************************************************************************/
4917
/*                        GDALDatasetIsLayerPrivate()                   */
4918
/************************************************************************/
4919
4920
/**
4921
 \brief Returns true if the layer at the specified index is deemed a private or
4922
 system table, or an internal detail only.
4923
4924
 This function is the same as the C++ method GDALDataset::IsLayerPrivate()
4925
4926
 @since GDAL 3.4
4927
4928
 @param hDS the dataset handle.
4929
 @param iLayer a layer number between 0 and GetLayerCount()-1.
4930
4931
 @return true if the layer is a private or system table.
4932
*/
4933
4934
int GDALDatasetIsLayerPrivate(GDALDatasetH hDS, int iLayer)
4935
4936
0
{
4937
0
    VALIDATE_POINTER1(hDS, "GDALDatasetIsLayerPrivate", false);
4938
4939
0
    const bool res = GDALDataset::FromHandle(hDS)->IsLayerPrivate(iLayer);
4940
4941
0
    return res ? 1 : 0;
4942
0
}
4943
4944
/************************************************************************/
4945
/*                            GetLayerIndex()                           */
4946
/************************************************************************/
4947
4948
/**
4949
 \brief Returns the index of the layer specified by name.
4950
4951
 @since GDAL 3.12
4952
4953
 @param pszName layer name (not NULL)
4954
4955
 @return an index >= 0, or -1 if not found.
4956
*/
4957
4958
int GDALDataset::GetLayerIndex(const char *pszName)
4959
0
{
4960
0
    const int nLayerCount = GetLayerCount();
4961
0
    int iMatch = -1;
4962
0
    for (int i = 0; i < nLayerCount; ++i)
4963
0
    {
4964
0
        if (const auto poLayer = GetLayer(i))
4965
0
        {
4966
0
            const char *pszLayerName = poLayer->GetDescription();
4967
0
            if (strcmp(pszName, pszLayerName) == 0)
4968
0
            {
4969
0
                iMatch = i;
4970
0
                break;
4971
0
            }
4972
0
            else if (EQUAL(pszName, pszLayerName))
4973
0
            {
4974
0
                iMatch = i;
4975
0
            }
4976
0
        }
4977
0
    }
4978
0
    return iMatch;
4979
0
}
4980
4981
/************************************************************************/
4982
/*                        GDALDatasetDeleteLayer()                      */
4983
/************************************************************************/
4984
4985
/**
4986
 \brief Delete the indicated layer from the datasource.
4987
4988
 If this function is supported
4989
 the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
4990
4991
 This method is the same as the C++ method GDALDataset::DeleteLayer().
4992
4993
 @since GDAL 2.0
4994
4995
 @param hDS the dataset handle.
4996
 @param iLayer the index of the layer to delete.
4997
4998
 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
4999
 layers is not supported for this datasource.
5000
5001
*/
5002
OGRErr GDALDatasetDeleteLayer(GDALDatasetH hDS, int iLayer)
5003
5004
0
{
5005
0
    VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
5006
5007
0
#ifdef OGRAPISPY_ENABLED
5008
0
    if (bOGRAPISpyEnabled)
5009
0
        OGRAPISpy_DS_DeleteLayer(hDS, iLayer);
5010
0
#endif
5011
5012
0
    return GDALDataset::FromHandle(hDS)->DeleteLayer(iLayer);
5013
0
}
5014
5015
/************************************************************************/
5016
/*                            CreateLayer()                             */
5017
/************************************************************************/
5018
5019
/**
5020
\brief This method attempts to create a new layer on the dataset with the
5021
indicated name, coordinate system, geometry type.
5022
5023
The papszOptions argument
5024
can be used to control driver specific creation options.  These options are
5025
normally documented in the format specific documentation.
5026
That function will try to validate the creation option list passed to the
5027
driver with the GDALValidateCreationOptions() method. This check can be
5028
disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5029
to NO.
5030
5031
Drivers should extend the ICreateLayer() method and not
5032
CreateLayer(). CreateLayer() adds validation of layer creation options, before
5033
delegating the actual work to ICreateLayer().
5034
5035
This method is the same as the C function GDALDatasetCreateLayer() and the
5036
deprecated OGR_DS_CreateLayer().
5037
5038
Example:
5039
5040
\code{.cpp}
5041
#include "gdal.h"
5042
#include "cpl_string.h"
5043
5044
...
5045
5046
        OGRLayer *poLayer;
5047
        char     **papszOptions;
5048
5049
        if( !poDS->TestCapability( ODsCCreateLayer ) )
5050
        {
5051
        ...
5052
        }
5053
5054
        papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5055
        poLayer = poDS->CreateLayer( "NewLayer", nullptr, wkbUnknown,
5056
                                     papszOptions );
5057
        CSLDestroy( papszOptions );
5058
5059
        if( poLayer == NULL )
5060
        {
5061
            ...
5062
        }
5063
\endcode
5064
5065
@param pszName the name for the new layer.  This should ideally not
5066
match any existing layer on the datasource.
5067
@param poSpatialRef the coordinate system to use for the new layer, or NULL if
5068
no coordinate system is available.
5069
@param eGType the geometry type for the layer.  Use wkbUnknown if there
5070
are no constraints on the types geometry to be written.
5071
@param papszOptions a StringList of name=value options.  Options are driver
5072
specific.
5073
5074
@return NULL is returned on failure, or a new OGRLayer handle on success.
5075
5076
*/
5077
5078
OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5079
                                   const OGRSpatialReference *poSpatialRef,
5080
                                   OGRwkbGeometryType eGType,
5081
                                   CSLConstList papszOptions)
5082
5083
0
{
5084
0
    if (eGType == wkbNone)
5085
0
    {
5086
0
        return CreateLayer(pszName, nullptr, papszOptions);
5087
0
    }
5088
0
    else
5089
0
    {
5090
0
        OGRGeomFieldDefn oGeomFieldDefn("", eGType);
5091
0
        oGeomFieldDefn.SetSpatialRef(poSpatialRef);
5092
0
        return CreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5093
0
    }
5094
0
}
5095
5096
/**
5097
\brief This method attempts to create a new layer on the dataset with the
5098
indicated name and geometry field definition.
5099
5100
When poGeomFieldDefn is not null, most drivers should honor
5101
poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5102
Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5103
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5104
poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5105
very few currently.
5106
5107
Note that even if a geometry coordinate precision is set and a driver honors the
5108
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5109
OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5110
with the coordinate precision. That is they are assumed to be valid once their
5111
coordinates are rounded to it. If it might not be the case, the user may set
5112
the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5113
or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5114
the passed geometries.
5115
5116
The papszOptions argument
5117
can be used to control driver specific creation options. These options are
5118
normally documented in the format specific documentation.
5119
This function will try to validate the creation option list passed to the
5120
driver with the GDALValidateCreationOptions() method. This check can be
5121
disabled by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS set
5122
to NO.
5123
5124
Drivers should extend the ICreateLayer() method and not
5125
CreateLayer(). CreateLayer() adds validation of layer creation options, before
5126
delegating the actual work to ICreateLayer().
5127
5128
This method is the same as the C function GDALDatasetCreateLayerFromGeomFieldDefn().
5129
5130
@param pszName the name for the new layer.  This should ideally not
5131
match any existing layer on the datasource.
5132
@param poGeomFieldDefn the geometry field definition to use for the new layer,
5133
or NULL if there is no geometry field.
5134
@param papszOptions a StringList of name=value options.  Options are driver
5135
specific.
5136
5137
@return NULL is returned on failure, or a new OGRLayer handle on success.
5138
@since 3.9
5139
5140
*/
5141
5142
OGRLayer *GDALDataset::CreateLayer(const char *pszName,
5143
                                   const OGRGeomFieldDefn *poGeomFieldDefn,
5144
                                   CSLConstList papszOptions)
5145
5146
0
{
5147
0
    if (CPLTestBool(
5148
0
            CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
5149
0
    {
5150
0
        ValidateLayerCreationOptions(papszOptions);
5151
0
    }
5152
5153
0
    OGRLayer *poLayer;
5154
0
    if (poGeomFieldDefn)
5155
0
    {
5156
0
        OGRGeomFieldDefn oGeomFieldDefn(poGeomFieldDefn);
5157
0
        if (OGR_GT_IsNonLinear(poGeomFieldDefn->GetType()) &&
5158
0
            !TestCapability(ODsCCurveGeometries))
5159
0
        {
5160
0
            oGeomFieldDefn.SetType(
5161
0
                OGR_GT_GetLinear(poGeomFieldDefn->GetType()));
5162
0
        }
5163
5164
0
        poLayer = ICreateLayer(pszName, &oGeomFieldDefn, papszOptions);
5165
0
    }
5166
0
    else
5167
0
    {
5168
0
        poLayer = ICreateLayer(pszName, nullptr, papszOptions);
5169
0
    }
5170
0
#ifdef DEBUG
5171
0
    if (poLayer != nullptr && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
5172
0
        !poLayer->TestCapability(OLCCurveGeometries))
5173
0
    {
5174
0
        CPLError(CE_Warning, CPLE_AppDefined,
5175
0
                 "Inconsistent driver: Layer geometry type is non-linear, but "
5176
0
                 "TestCapability(OLCCurveGeometries) returns FALSE.");
5177
0
    }
5178
0
#endif
5179
5180
0
    return poLayer;
5181
0
}
5182
5183
//! @cond Doxygen_Suppress
5184
5185
// Technical override to avoid ambiguous choice between the old and new
5186
// new CreateLayer() signatures.
5187
OGRLayer *GDALDataset::CreateLayer(const char *pszName)
5188
0
{
5189
0
    OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5190
0
    return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5191
0
}
5192
5193
// Technical override to avoid ambiguous choice between the old and new
5194
// new CreateLayer() signatures.
5195
OGRLayer *GDALDataset::CreateLayer(const char *pszName, std::nullptr_t)
5196
0
{
5197
0
    OGRGeomFieldDefn oGeomFieldDefn("", wkbUnknown);
5198
0
    return CreateLayer(pszName, &oGeomFieldDefn, nullptr);
5199
0
}
5200
5201
//!@endcond
5202
5203
/************************************************************************/
5204
/*                         GDALDatasetCreateLayer()                     */
5205
/************************************************************************/
5206
5207
/**
5208
\brief This function attempts to create a new layer on the dataset with the
5209
indicated name, coordinate system, geometry type.
5210
5211
The papszOptions argument can be used to control driver specific creation
5212
options.  These options are normally documented in the format specific
5213
documentation.
5214
5215
This method is the same as the C++ method GDALDataset::CreateLayer().
5216
5217
Example:
5218
5219
\code{.c}
5220
#include "gdal.h"
5221
#include "cpl_string.h"
5222
5223
...
5224
5225
        OGRLayerH  hLayer;
5226
        char     **papszOptions;
5227
5228
        if( !GDALDatasetTestCapability( hDS, ODsCCreateLayer ) )
5229
        {
5230
        ...
5231
        }
5232
5233
        papszOptions = CSLSetNameValue( papszOptions, "DIM", "2" );
5234
        hLayer = GDALDatasetCreateLayer( hDS, "NewLayer", NULL, wkbUnknown,
5235
                                         papszOptions );
5236
        CSLDestroy( papszOptions );
5237
5238
        if( hLayer == NULL )
5239
        {
5240
            ...
5241
        }
5242
\endcode
5243
5244
@since GDAL 2.0
5245
5246
@param hDS the dataset handle
5247
@param pszName the name for the new layer.  This should ideally not
5248
match any existing layer on the datasource.
5249
@param hSpatialRef the coordinate system to use for the new layer, or NULL if
5250
no coordinate system is available.
5251
@param eGType the geometry type for the layer.  Use wkbUnknown if there
5252
are no constraints on the types geometry to be written.
5253
@param papszOptions a StringList of name=value options.  Options are driver
5254
specific.
5255
5256
@return NULL is returned on failure, or a new OGRLayer handle on success.
5257
5258
*/
5259
5260
OGRLayerH GDALDatasetCreateLayer(GDALDatasetH hDS, const char *pszName,
5261
                                 OGRSpatialReferenceH hSpatialRef,
5262
                                 OGRwkbGeometryType eGType,
5263
                                 CSLConstList papszOptions)
5264
5265
0
{
5266
0
    VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", nullptr);
5267
5268
0
    if (pszName == nullptr)
5269
0
    {
5270
0
        CPLError(CE_Failure, CPLE_ObjectNull,
5271
0
                 "Name was NULL in GDALDatasetCreateLayer");
5272
0
        return nullptr;
5273
0
    }
5274
5275
0
    OGRLayerH hLayer =
5276
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5277
0
            pszName, OGRSpatialReference::FromHandle(hSpatialRef), eGType,
5278
0
            const_cast<char **>(papszOptions)));
5279
5280
0
#ifdef OGRAPISPY_ENABLED
5281
0
    if (bOGRAPISpyEnabled)
5282
0
        OGRAPISpy_DS_CreateLayer(hDS, pszName, hSpatialRef, eGType,
5283
0
                                 const_cast<char **>(papszOptions), hLayer);
5284
0
#endif
5285
5286
0
    return hLayer;
5287
0
}
5288
5289
/************************************************************************/
5290
/*                 GDALDatasetCreateLayerFromGeomFieldDefn()            */
5291
/************************************************************************/
5292
5293
/**
5294
\brief This function attempts to create a new layer on the dataset with the
5295
indicated name and geometry field.
5296
5297
When poGeomFieldDefn is not null, most drivers should honor
5298
poGeomFieldDefn->GetType() and poGeomFieldDefn->GetSpatialRef().
5299
Drivers that honor poGeomFieldDefn->GetCoordinatePrecision() will declare the
5300
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability. Drivers may honor
5301
poGeomFieldDefn->GetNameRef() and poGeomFieldDefn->IsNullable(), but there are
5302
very few currently.
5303
5304
Note that even if a geometry coordinate precision is set and a driver honors the
5305
GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION capability, geometries passed to
5306
OGRLayer::CreateFeature() and OGRLayer::SetFeature() are assumed to be compatible
5307
with the coordinate precision. That is they are assumed to be valid once their
5308
coordinates are rounded to it. If it might not be the case, the user may set
5309
the OGR_APPLY_GEOM_SET_PRECISION configuration option before calling CreateFeature()
5310
or SetFeature() to force the OGRGeometry::SetPrecision() method to be called on
5311
the passed geometries.
5312
5313
The papszOptions argument can be used to control driver specific creation
5314
options.  These options are normally documented in the format specific
5315
documentation.
5316
5317
This method is the same as the C++ method GDALDataset::CreateLayer().
5318
5319
@param hDS the dataset handle
5320
@param pszName the name for the new layer.  This should ideally not
5321
match any existing layer on the datasource.
5322
@param hGeomFieldDefn the geometry field definition. May be NULL to indicate
5323
a non-spatial file (or if adding geometry fields later with OGR_L_CreateGeomField()
5324
for drivers supporting that interface).
5325
@param papszOptions a StringList of name=value options.  Options are driver
5326
specific.
5327
5328
@return NULL is returned on failure, or a new OGRLayer handle on success.
5329
5330
@since GDAL 3.9
5331
5332
*/
5333
5334
OGRLayerH
5335
GDALDatasetCreateLayerFromGeomFieldDefn(GDALDatasetH hDS, const char *pszName,
5336
                                        OGRGeomFieldDefnH hGeomFieldDefn,
5337
                                        CSLConstList papszOptions)
5338
5339
0
{
5340
0
    VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayerFromGeomFieldDefn", nullptr);
5341
5342
0
    if (!pszName)
5343
0
    {
5344
0
        CPLError(CE_Failure, CPLE_ObjectNull,
5345
0
                 "Name was NULL in GDALDatasetCreateLayerFromGeomFieldDefn");
5346
0
        return nullptr;
5347
0
    }
5348
5349
0
    OGRLayerH hLayer =
5350
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CreateLayer(
5351
0
            pszName, OGRGeomFieldDefn::FromHandle(hGeomFieldDefn),
5352
0
            papszOptions));
5353
0
    return hLayer;
5354
0
}
5355
5356
/************************************************************************/
5357
/*                         GDALDatasetCopyLayer()                       */
5358
/************************************************************************/
5359
5360
/**
5361
 \brief Duplicate an existing layer.
5362
5363
 This function creates a new layer, duplicate the field definitions of the
5364
 source layer and then duplicate each features of the source layer.
5365
 The papszOptions argument
5366
 can be used to control driver specific creation options.  These options are
5367
 normally documented in the format specific documentation.
5368
 The source layer may come from another dataset.
5369
5370
 This method is the same as the C++ method GDALDataset::CopyLayer()
5371
5372
 @since GDAL 2.0
5373
5374
 @param hDS the dataset handle.
5375
 @param hSrcLayer source layer.
5376
 @param pszNewName the name of the layer to create.
5377
 @param papszOptions a StringList of name=value options.  Options are driver
5378
                     specific.
5379
5380
 @return a handle to the layer, or NULL if an error occurs.
5381
*/
5382
OGRLayerH GDALDatasetCopyLayer(GDALDatasetH hDS, OGRLayerH hSrcLayer,
5383
                               const char *pszNewName,
5384
                               CSLConstList papszOptions)
5385
5386
0
{
5387
0
    VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", nullptr);
5388
0
    VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", nullptr);
5389
0
    VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", nullptr);
5390
5391
0
    return OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->CopyLayer(
5392
0
        OGRLayer::FromHandle(hSrcLayer), pszNewName,
5393
0
        const_cast<char **>(papszOptions)));
5394
0
}
5395
5396
/************************************************************************/
5397
/*                        GDALDatasetExecuteSQL()                       */
5398
/************************************************************************/
5399
5400
/**
5401
 \brief Execute an SQL statement against the data store.
5402
5403
 The result of an SQL query is either NULL for statements that are in error,
5404
 or that have no results set, or an OGRLayer pointer representing a results
5405
 set from the query.  Note that this OGRLayer is in addition to the layers
5406
 in the data store and must be destroyed with
5407
 ReleaseResultSet() before the dataset is closed
5408
 (destroyed).
5409
5410
 This method is the same as the C++ method GDALDataset::ExecuteSQL()
5411
5412
 For more information on the SQL dialect supported internally by OGR
5413
 review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
5414
 document.  Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
5415
 to the underlying RDBMS.
5416
5417
 Starting with OGR 1.10, the <a
5418
 href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
5419
 also be used.
5420
5421
 @since GDAL 2.0
5422
5423
 @param hDS the dataset handle.
5424
 @param pszStatement the SQL statement to execute.
5425
 @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
5426
5427
 @param pszDialect allows control of the statement dialect. If set to NULL, the
5428
 OGR SQL engine will be used, except for RDBMS drivers that will use their
5429
 dedicated SQL engine, unless OGRSQL is explicitly passed as the
5430
 dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
5431
5432
 @return an OGRLayer containing the results of the query.  Deallocate with
5433
 GDALDatasetReleaseResultSet().
5434
5435
*/
5436
5437
OGRLayerH GDALDatasetExecuteSQL(GDALDatasetH hDS, const char *pszStatement,
5438
                                OGRGeometryH hSpatialFilter,
5439
                                const char *pszDialect)
5440
5441
0
{
5442
0
    VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", nullptr);
5443
5444
0
    OGRLayerH hLayer =
5445
0
        OGRLayer::ToHandle(GDALDataset::FromHandle(hDS)->ExecuteSQL(
5446
0
            pszStatement, OGRGeometry::FromHandle(hSpatialFilter), pszDialect));
5447
5448
0
#ifdef OGRAPISPY_ENABLED
5449
0
    if (bOGRAPISpyEnabled)
5450
0
        OGRAPISpy_DS_ExecuteSQL(hDS, pszStatement, hSpatialFilter, pszDialect,
5451
0
                                hLayer);
5452
0
#endif
5453
5454
0
    return hLayer;
5455
0
}
5456
5457
/************************************************************************/
5458
/*                        GDALDatasetAbortSQL()                         */
5459
/************************************************************************/
5460
5461
/**
5462
 \brief Abort any SQL statement running in the data store.
5463
5464
 This function can be safely called from any thread (pending that the dataset
5465
 object is still alive). Driver implementations will make sure that it can be
5466
 called in a thread-safe way.
5467
5468
 This might not be implemented by all drivers. At time of writing, only SQLite,
5469
 GPKG and PG drivers implement it
5470
5471
 This method is the same as the C++ method GDALDataset::AbortSQL()
5472
5473
 @since GDAL 3.2.0
5474
5475
 @param hDS the dataset handle.
5476
5477
 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if AbortSQL
5478
 is not supported for this datasource. .
5479
5480
*/
5481
5482
OGRErr GDALDatasetAbortSQL(GDALDatasetH hDS)
5483
5484
0
{
5485
0
    VALIDATE_POINTER1(hDS, "GDALDatasetAbortSQL", OGRERR_FAILURE);
5486
0
    return GDALDataset::FromHandle(hDS)->AbortSQL();
5487
0
}
5488
5489
/************************************************************************/
5490
/*                      GDALDatasetGetStyleTable()                      */
5491
/************************************************************************/
5492
5493
/**
5494
 \brief Returns dataset style table.
5495
5496
 This function is the same as the C++ method GDALDataset::GetStyleTable()
5497
5498
 @since GDAL 2.0
5499
5500
 @param hDS the dataset handle
5501
 @return handle to a style table which should not be modified or freed by the
5502
 caller.
5503
*/
5504
5505
OGRStyleTableH GDALDatasetGetStyleTable(GDALDatasetH hDS)
5506
5507
0
{
5508
0
    VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", nullptr);
5509
5510
0
    return reinterpret_cast<OGRStyleTableH>(
5511
0
        GDALDataset::FromHandle(hDS)->GetStyleTable());
5512
0
}
5513
5514
/************************************************************************/
5515
/*                    GDALDatasetSetStyleTableDirectly()                */
5516
/************************************************************************/
5517
5518
/**
5519
 \brief Set dataset style table.
5520
5521
 This function operate exactly as GDALDatasetSetStyleTable() except that it
5522
 assumes ownership of the passed table.
5523
5524
 This function is the same as the C++ method
5525
 GDALDataset::SetStyleTableDirectly()
5526
5527
 @since GDAL 2.0
5528
5529
 @param hDS the dataset handle
5530
 @param hStyleTable style table handle to set
5531
5532
*/
5533
5534
void GDALDatasetSetStyleTableDirectly(GDALDatasetH hDS,
5535
                                      OGRStyleTableH hStyleTable)
5536
5537
0
{
5538
0
    VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
5539
5540
0
    GDALDataset::FromHandle(hDS)->SetStyleTableDirectly(
5541
0
        reinterpret_cast<OGRStyleTable *>(hStyleTable));
5542
0
}
5543
5544
/************************************************************************/
5545
/*                     GDALDatasetSetStyleTable()                       */
5546
/************************************************************************/
5547
5548
/**
5549
 \brief Set dataset style table.
5550
5551
 This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
5552
 it assumes ownership of the passed table.
5553
5554
 This function is the same as the C++ method GDALDataset::SetStyleTable()
5555
5556
 @since GDAL 2.0
5557
5558
 @param hDS the dataset handle
5559
 @param hStyleTable style table handle to set
5560
5561
*/
5562
5563
void GDALDatasetSetStyleTable(GDALDatasetH hDS, OGRStyleTableH hStyleTable)
5564
5565
0
{
5566
0
    VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
5567
0
    VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
5568
5569
0
    GDALDataset::FromHandle(hDS)->SetStyleTable(
5570
0
        reinterpret_cast<OGRStyleTable *>(hStyleTable));
5571
0
}
5572
5573
/************************************************************************/
5574
/*                    ValidateLayerCreationOptions()                    */
5575
/************************************************************************/
5576
5577
//! @cond Doxygen_Suppress
5578
int GDALDataset::ValidateLayerCreationOptions(const char *const *papszLCO)
5579
0
{
5580
0
    const char *pszOptionList =
5581
0
        GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5582
0
    if (pszOptionList == nullptr && poDriver != nullptr)
5583
0
    {
5584
0
        pszOptionList =
5585
0
            poDriver->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
5586
0
    }
5587
0
    CPLString osDataset;
5588
0
    osDataset.Printf("dataset %s", GetDescription());
5589
0
    return GDALValidateOptions(pszOptionList, papszLCO, "layer creation option",
5590
0
                               osDataset);
5591
0
}
5592
5593
//! @endcond
5594
5595
/************************************************************************/
5596
/*                              Release()                               */
5597
/************************************************************************/
5598
5599
/**
5600
\brief Drop a reference to this dataset, and if the reference count drops to one
5601
close (destroy) the dataset.
5602
5603
This method is the same as the C function OGRReleaseDataSource().
5604
5605
@deprecated. In GDAL 2, use GDALClose() instead
5606
5607
@return OGRERR_NONE on success or an error code.
5608
*/
5609
5610
OGRErr GDALDataset::Release()
5611
5612
0
{
5613
0
    ReleaseRef();
5614
0
    return OGRERR_NONE;
5615
0
}
5616
5617
/************************************************************************/
5618
/*                            GetRefCount()                             */
5619
/************************************************************************/
5620
5621
/**
5622
\brief Fetch reference count.
5623
5624
This method is the same as the C function OGR_DS_GetRefCount().
5625
5626
In GDAL 1.X, this method used to be in the OGRDataSource class.
5627
5628
@return the current reference count for the datasource object itself.
5629
*/
5630
5631
int GDALDataset::GetRefCount() const
5632
0
{
5633
0
    return nRefCount;
5634
0
}
5635
5636
/************************************************************************/
5637
/*                         GetSummaryRefCount()                         */
5638
/************************************************************************/
5639
5640
/**
5641
\brief Fetch reference count of datasource and all owned layers.
5642
5643
This method is the same as the C function  OGR_DS_GetSummaryRefCount().
5644
5645
In GDAL 1.X, this method used to be in the OGRDataSource class.
5646
5647
@deprecated
5648
5649
@return the current summary reference count for the datasource and its layers.
5650
*/
5651
5652
int GDALDataset::GetSummaryRefCount() const
5653
5654
0
{
5655
0
    CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
5656
0
    int nSummaryCount = nRefCount;
5657
0
    GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
5658
5659
0
    for (int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer)
5660
0
        nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
5661
5662
0
    return nSummaryCount;
5663
0
}
5664
5665
/************************************************************************/
5666
/*                           ICreateLayer()                             */
5667
/************************************************************************/
5668
5669
/**
5670
 \brief This method attempts to create a new layer on the dataset with the
5671
 indicated name, coordinate system, geometry type.
5672
5673
 This method is reserved to implementation by drivers.
5674
5675
 The papszOptions argument can be used to control driver specific creation
5676
 options.  These options are normally documented in the format specific
5677
 documentation.
5678
5679
 @param pszName the name for the new layer.  This should ideally not
5680
 match any existing layer on the datasource.
5681
 @param poGeomFieldDefn the geometry field definition to use for the new layer,
5682
 or NULL if there is no geometry field.
5683
 @param papszOptions a StringList of name=value options.  Options are driver
5684
 specific.
5685
5686
 @return NULL is returned on failure, or a new OGRLayer handle on success.
5687
5688
 @since GDAL 2.0 (prototype modified in 3.9)
5689
*/
5690
5691
OGRLayer *
5692
GDALDataset::ICreateLayer(CPL_UNUSED const char *pszName,
5693
                          CPL_UNUSED const OGRGeomFieldDefn *poGeomFieldDefn,
5694
                          CPL_UNUSED CSLConstList papszOptions)
5695
5696
0
{
5697
0
    CPLError(CE_Failure, CPLE_NotSupported,
5698
0
             "CreateLayer() not supported by this dataset.");
5699
5700
0
    return nullptr;
5701
0
}
5702
5703
/************************************************************************/
5704
/*                             CopyLayer()                              */
5705
/************************************************************************/
5706
5707
/**
5708
 \brief Duplicate an existing layer.
5709
5710
 This method creates a new layer, duplicate the field definitions of the
5711
 source layer and then duplicate each features of the source layer.
5712
 The papszOptions argument
5713
 can be used to control driver specific creation options.  These options are
5714
 normally documented in the format specific documentation.
5715
 The source layer may come from another dataset.
5716
5717
 This method is the same as the C function GDALDatasetCopyLayer() and the
5718
 deprecated OGR_DS_CopyLayer().
5719
5720
 In GDAL 1.X, this method used to be in the OGRDataSource class.
5721
5722
 @param poSrcLayer source layer.
5723
 @param pszNewName the name of the layer to create.
5724
 @param papszOptions a StringList of name=value options.  Options are driver
5725
                     specific. There is a common option to set output layer
5726
                     spatial reference: DST_SRSWKT. The option should be in
5727
                     WKT format. Starting with GDAL 3.7, the common option
5728
                     COPY_MD can be set to NO to prevent the default copying
5729
                     of the metadata from the source layer to the target layer.
5730
5731
 @return a handle to the layer, or NULL if an error occurs.
5732
*/
5733
5734
OGRLayer *GDALDataset::CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
5735
                                 char **papszOptions)
5736
5737
0
{
5738
    /* -------------------------------------------------------------------- */
5739
    /*      Create the layer.                                               */
5740
    /* -------------------------------------------------------------------- */
5741
0
    if (!TestCapability(ODsCCreateLayer))
5742
0
    {
5743
0
        CPLError(CE_Failure, CPLE_NotSupported,
5744
0
                 "This datasource does not support creation of layers.");
5745
0
        return nullptr;
5746
0
    }
5747
5748
0
    const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
5749
0
    OGRSpatialReference oDstSpaRef(pszSRSWKT);
5750
0
    oDstSpaRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5751
0
    OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
5752
0
    OGRLayer *poDstLayer = nullptr;
5753
5754
0
    CPLStringList aosCleanedUpOptions(CSLDuplicate(papszOptions));
5755
0
    aosCleanedUpOptions.SetNameValue("DST_SRSWKT", nullptr);
5756
0
    aosCleanedUpOptions.SetNameValue("COPY_MD", nullptr);
5757
5758
0
    CPLErrorReset();
5759
0
    const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
5760
0
    if (nSrcGeomFieldCount == 1)
5761
0
    {
5762
0
        OGRGeomFieldDefn oGeomFieldDefn(poSrcDefn->GetGeomFieldDefn(0));
5763
0
        if (pszSRSWKT)
5764
0
            oGeomFieldDefn.SetSpatialRef(&oDstSpaRef);
5765
0
        poDstLayer = ICreateLayer(pszNewName, &oGeomFieldDefn,
5766
0
                                  aosCleanedUpOptions.List());
5767
0
    }
5768
0
    else
5769
0
    {
5770
0
        poDstLayer =
5771
0
            ICreateLayer(pszNewName, nullptr, aosCleanedUpOptions.List());
5772
0
    }
5773
5774
0
    if (poDstLayer == nullptr)
5775
0
        return nullptr;
5776
5777
0
    if (CPLTestBool(CSLFetchNameValueDef(papszOptions, "COPY_MD", "YES")))
5778
0
    {
5779
0
        char **papszMD = poSrcLayer->GetMetadata();
5780
0
        if (papszMD)
5781
0
            poDstLayer->SetMetadata(papszMD);
5782
0
    }
5783
5784
    /* -------------------------------------------------------------------- */
5785
    /*      Add fields.  Default to copy all fields, and make sure to       */
5786
    /*      establish a mapping between indices, rather than names, in      */
5787
    /*      case the target datasource has altered it (e.g. Shapefile       */
5788
    /*      limited to 10 char field names).                                */
5789
    /* -------------------------------------------------------------------- */
5790
0
    const int nSrcFieldCount = poSrcDefn->GetFieldCount();
5791
5792
    // Initialize the index-to-index map to -1's.
5793
0
    std::vector<int> anMap(nSrcFieldCount, -1);
5794
5795
    // Caution: At the time of writing, the MapInfo driver
5796
    // returns NULL until a field has been added.
5797
0
    OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
5798
0
    int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
5799
0
    for (int iField = 0; iField < nSrcFieldCount; ++iField)
5800
0
    {
5801
0
        OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
5802
0
        OGRFieldDefn oFieldDefn(poSrcFieldDefn);
5803
5804
        // The field may have been already created at layer creation.
5805
0
        int iDstField = -1;
5806
0
        if (poDstFDefn)
5807
0
            iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
5808
0
        if (iDstField >= 0)
5809
0
        {
5810
0
            anMap[iField] = iDstField;
5811
0
        }
5812
0
        else if (poDstLayer->CreateField(&oFieldDefn) == OGRERR_NONE)
5813
0
        {
5814
            // Now that we've created a field, GetLayerDefn() won't return NULL.
5815
0
            if (poDstFDefn == nullptr)
5816
0
                poDstFDefn = poDstLayer->GetLayerDefn();
5817
5818
            // Sanity check: if it fails, the driver is buggy.
5819
0
            if (poDstFDefn != nullptr &&
5820
0
                poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
5821
0
            {
5822
0
                CPLError(CE_Warning, CPLE_AppDefined,
5823
0
                         "The output driver has claimed to have added the %s "
5824
0
                         "field, but it did not!",
5825
0
                         oFieldDefn.GetNameRef());
5826
0
            }
5827
0
            else
5828
0
            {
5829
0
                anMap[iField] = nDstFieldCount;
5830
0
                ++nDstFieldCount;
5831
0
            }
5832
0
        }
5833
0
    }
5834
5835
    /* -------------------------------------------------------------------- */
5836
0
    std::unique_ptr<OGRCoordinateTransformation> poCT;
5837
0
    OGRSpatialReference *sourceSRS = poSrcLayer->GetSpatialRef();
5838
0
    if (sourceSRS != nullptr && pszSRSWKT != nullptr && !oDstSpaRef.IsEmpty() &&
5839
0
        sourceSRS->IsSame(&oDstSpaRef) == FALSE)
5840
0
    {
5841
0
        poCT.reset(OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef));
5842
0
        if (nullptr == poCT)
5843
0
        {
5844
0
            CPLError(CE_Failure, CPLE_NotSupported,
5845
0
                     "This input/output spatial reference is not supported.");
5846
0
            return nullptr;
5847
0
        }
5848
0
    }
5849
    /* -------------------------------------------------------------------- */
5850
    /*      Create geometry fields.                                         */
5851
    /* -------------------------------------------------------------------- */
5852
0
    if (nSrcGeomFieldCount > 1 &&
5853
0
        TestCapability(ODsCCreateGeomFieldAfterCreateLayer))
5854
0
    {
5855
5856
0
        for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5857
0
        {
5858
0
            if (nullptr == pszSRSWKT)
5859
0
            {
5860
0
                poDstLayer->CreateGeomField(
5861
0
                    poSrcDefn->GetGeomFieldDefn(iField));
5862
0
            }
5863
0
            else
5864
0
            {
5865
0
                OGRGeomFieldDefn *pDstGeomFieldDefn =
5866
0
                    poSrcDefn->GetGeomFieldDefn(iField);
5867
0
                pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
5868
0
                poDstLayer->CreateGeomField(pDstGeomFieldDefn);
5869
0
            }
5870
0
        }
5871
0
    }
5872
5873
    /* -------------------------------------------------------------------- */
5874
    /*      Check if the destination layer supports transactions and set a  */
5875
    /*      default number of features in a single transaction.             */
5876
    /* -------------------------------------------------------------------- */
5877
0
    const int nGroupTransactions =
5878
0
        poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
5879
5880
    /* -------------------------------------------------------------------- */
5881
    /*      Transfer features.                                              */
5882
    /* -------------------------------------------------------------------- */
5883
0
    poSrcLayer->ResetReading();
5884
5885
0
    if (nGroupTransactions <= 0)
5886
0
    {
5887
0
        while (true)
5888
0
        {
5889
0
            auto poFeature =
5890
0
                std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5891
5892
0
            if (poFeature == nullptr)
5893
0
                break;
5894
5895
0
            CPLErrorReset();
5896
0
            auto poDstFeature =
5897
0
                std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5898
5899
0
            if (poDstFeature->SetFrom(poFeature.get(), anMap.data(), TRUE) !=
5900
0
                OGRERR_NONE)
5901
0
            {
5902
0
                CPLError(CE_Failure, CPLE_AppDefined,
5903
0
                         "Unable to translate feature " CPL_FRMT_GIB
5904
0
                         " from layer %s.",
5905
0
                         poFeature->GetFID(), poSrcDefn->GetName());
5906
0
                return poDstLayer;
5907
0
            }
5908
5909
0
            if (nullptr != poCT)
5910
0
            {
5911
0
                for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5912
0
                {
5913
0
                    OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
5914
0
                    if (nullptr == pGeom)
5915
0
                        continue;
5916
5917
0
                    const OGRErr eErr = pGeom->transform(poCT.get());
5918
0
                    if (eErr == OGRERR_NONE)
5919
0
                        continue;
5920
5921
0
                    CPLError(CE_Failure, CPLE_AppDefined,
5922
0
                             "Unable to transform geometry " CPL_FRMT_GIB
5923
0
                             " from layer %s.",
5924
0
                             poFeature->GetFID(), poSrcDefn->GetName());
5925
0
                    return poDstLayer;
5926
0
                }
5927
0
            }
5928
5929
0
            poDstFeature->SetFID(poFeature->GetFID());
5930
5931
0
            CPLErrorReset();
5932
0
            if (poDstLayer->CreateFeature(poDstFeature.get()) != OGRERR_NONE)
5933
0
            {
5934
0
                return poDstLayer;
5935
0
            }
5936
0
        }
5937
0
    }
5938
0
    else
5939
0
    {
5940
0
        std::vector<std::unique_ptr<OGRFeature>> apoDstFeatures;
5941
0
        try
5942
0
        {
5943
0
            apoDstFeatures.resize(nGroupTransactions);
5944
0
        }
5945
0
        catch (const std::exception &e)
5946
0
        {
5947
0
            CPLError(CE_Failure, CPLE_OutOfMemory, "%s", e.what());
5948
0
            return poDstLayer;
5949
0
        }
5950
0
        bool bStopTransfer = false;
5951
0
        while (!bStopTransfer)
5952
0
        {
5953
            /* --------------------------------------------------------------------
5954
             */
5955
            /*      Fill the array with features. */
5956
            /* --------------------------------------------------------------------
5957
             */
5958
            // Number of features in the temporary array.
5959
0
            int nFeatCount = 0;  // Used after for.
5960
0
            for (nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount)
5961
0
            {
5962
0
                auto poFeature =
5963
0
                    std::unique_ptr<OGRFeature>(poSrcLayer->GetNextFeature());
5964
5965
0
                if (poFeature == nullptr)
5966
0
                {
5967
0
                    bStopTransfer = true;
5968
0
                    break;
5969
0
                }
5970
5971
0
                CPLErrorReset();
5972
0
                apoDstFeatures[nFeatCount] =
5973
0
                    std::make_unique<OGRFeature>(poDstLayer->GetLayerDefn());
5974
5975
0
                if (apoDstFeatures[nFeatCount]->SetFrom(
5976
0
                        poFeature.get(), anMap.data(), TRUE) != OGRERR_NONE)
5977
0
                {
5978
0
                    CPLError(CE_Failure, CPLE_AppDefined,
5979
0
                             "Unable to translate feature " CPL_FRMT_GIB
5980
0
                             " from layer %s.",
5981
0
                             poFeature->GetFID(), poSrcDefn->GetName());
5982
0
                    bStopTransfer = true;
5983
0
                    poFeature.reset();
5984
0
                    break;
5985
0
                }
5986
5987
0
                if (nullptr != poCT)
5988
0
                {
5989
0
                    for (int iField = 0; iField < nSrcGeomFieldCount; ++iField)
5990
0
                    {
5991
0
                        OGRGeometry *pGeom =
5992
0
                            apoDstFeatures[nFeatCount]->GetGeomFieldRef(iField);
5993
0
                        if (nullptr == pGeom)
5994
0
                            continue;
5995
5996
0
                        const OGRErr eErr = pGeom->transform(poCT.get());
5997
0
                        if (eErr == OGRERR_NONE)
5998
0
                            continue;
5999
6000
0
                        CPLError(CE_Failure, CPLE_AppDefined,
6001
0
                                 "Unable to transform geometry " CPL_FRMT_GIB
6002
0
                                 " from layer %s.",
6003
0
                                 poFeature->GetFID(), poSrcDefn->GetName());
6004
0
                        bStopTransfer = true;
6005
0
                        poFeature.reset();
6006
0
                        break;
6007
0
                    }
6008
0
                }
6009
6010
0
                if (poFeature)
6011
0
                {
6012
0
                    apoDstFeatures[nFeatCount]->SetFID(poFeature->GetFID());
6013
0
                }
6014
0
            }
6015
6016
0
            CPLErrorReset();
6017
0
            bool bStopTransaction = false;
6018
0
            while (!bStopTransaction)
6019
0
            {
6020
0
                bStopTransaction = true;
6021
0
                if (poDstLayer->StartTransaction() != OGRERR_NONE)
6022
0
                    break;
6023
0
                for (int i = 0; i < nFeatCount; ++i)
6024
0
                {
6025
0
                    if (poDstLayer->CreateFeature(apoDstFeatures[i].get()) !=
6026
0
                        OGRERR_NONE)
6027
0
                    {
6028
0
                        bStopTransfer = true;
6029
0
                        bStopTransaction = false;
6030
0
                        break;
6031
0
                    }
6032
0
                    apoDstFeatures[i].reset();
6033
0
                }
6034
0
                if (bStopTransaction)
6035
0
                {
6036
0
                    if (poDstLayer->CommitTransaction() != OGRERR_NONE)
6037
0
                        break;
6038
0
                }
6039
0
                else
6040
0
                {
6041
0
                    poDstLayer->RollbackTransaction();
6042
0
                }
6043
0
            }
6044
0
        }
6045
0
    }
6046
6047
0
    return poDstLayer;
6048
0
}
6049
6050
/************************************************************************/
6051
/*                            DeleteLayer()                             */
6052
/************************************************************************/
6053
6054
/**
6055
 \fn GDALDataset::DeleteLayer(int)
6056
 \brief Delete the indicated layer from the datasource.
6057
6058
 If this method is supported
6059
 the ODsCDeleteLayer capability will test TRUE on the GDALDataset.
6060
6061
 This method is the same as the C function GDALDatasetDeleteLayer() and the
6062
 deprecated OGR_DS_DeleteLayer().
6063
6064
 In GDAL 1.X, this method used to be in the OGRDataSource class.
6065
6066
 @param iLayer the index of the layer to delete.
6067
6068
 @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
6069
 layers is not supported for this datasource.
6070
6071
*/
6072
6073
OGRErr GDALDataset::DeleteLayer(CPL_UNUSED int iLayer)
6074
6075
0
{
6076
0
    CPLError(CE_Failure, CPLE_NotSupported,
6077
0
             "DeleteLayer() not supported by this dataset.");
6078
6079
0
    return OGRERR_UNSUPPORTED_OPERATION;
6080
0
}
6081
6082
/************************************************************************/
6083
/*                           GetLayerByName()                           */
6084
/************************************************************************/
6085
6086
/**
6087
 \brief Fetch a layer by name.
6088
6089
 The returned layer remains owned by the
6090
 GDALDataset and should not be deleted by the application.
6091
6092
 This method is the same as the C function GDALDatasetGetLayerByName() and the
6093
 deprecated OGR_DS_GetLayerByName().
6094
6095
 In GDAL 1.X, this method used to be in the OGRDataSource class.
6096
6097
 @param pszName the layer name of the layer to fetch.
6098
6099
 @return the layer, or NULL if Layer is not found or an error occurs.
6100
*/
6101
6102
OGRLayer *GDALDataset::GetLayerByName(const char *pszName)
6103
6104
0
{
6105
0
    CPLMutexHolderD(m_poPrivate ? &(m_poPrivate->hMutex) : nullptr);
6106
6107
0
    if (!pszName)
6108
0
        return nullptr;
6109
6110
    // First a case sensitive check.
6111
0
    for (int i = 0; i < GetLayerCount(); ++i)
6112
0
    {
6113
0
        OGRLayer *poLayer = GetLayer(i);
6114
6115
0
        if (strcmp(pszName, poLayer->GetName()) == 0)
6116
0
            return poLayer;
6117
0
    }
6118
6119
    // Then case insensitive.
6120
0
    for (int i = 0; i < GetLayerCount(); ++i)
6121
0
    {
6122
0
        OGRLayer *poLayer = GetLayer(i);
6123
6124
0
        if (EQUAL(pszName, poLayer->GetName()))
6125
0
            return poLayer;
6126
0
    }
6127
6128
0
    return nullptr;
6129
0
}
6130
6131
//! @cond Doxygen_Suppress
6132
/************************************************************************/
6133
/*                       ProcessSQLCreateIndex()                        */
6134
/*                                                                      */
6135
/*      The correct syntax for creating an index in our dialect of      */
6136
/*      SQL is:                                                         */
6137
/*                                                                      */
6138
/*        CREATE INDEX ON <layername> USING <columnname>                */
6139
/************************************************************************/
6140
6141
OGRErr GDALDataset::ProcessSQLCreateIndex(const char *pszSQLCommand)
6142
6143
0
{
6144
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6145
6146
    /* -------------------------------------------------------------------- */
6147
    /*      Do some general syntax checking.                                */
6148
    /* -------------------------------------------------------------------- */
6149
0
    if (CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0], "CREATE") ||
6150
0
        !EQUAL(papszTokens[1], "INDEX") || !EQUAL(papszTokens[2], "ON") ||
6151
0
        !EQUAL(papszTokens[4], "USING"))
6152
0
    {
6153
0
        CSLDestroy(papszTokens);
6154
0
        CPLError(CE_Failure, CPLE_AppDefined,
6155
0
                 "Syntax error in CREATE INDEX command.\n"
6156
0
                 "Was '%s'\n"
6157
0
                 "Should be of form 'CREATE INDEX ON <table> USING <field>'",
6158
0
                 pszSQLCommand);
6159
0
        return OGRERR_FAILURE;
6160
0
    }
6161
6162
    /* -------------------------------------------------------------------- */
6163
    /*      Find the named layer.                                           */
6164
    /* -------------------------------------------------------------------- */
6165
0
    OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6166
0
    if (poLayer == nullptr)
6167
0
    {
6168
0
        CPLError(CE_Failure, CPLE_AppDefined,
6169
0
                 "CREATE INDEX ON failed, no such layer as `%s'.",
6170
0
                 papszTokens[3]);
6171
0
        CSLDestroy(papszTokens);
6172
0
        return OGRERR_FAILURE;
6173
0
    }
6174
6175
    /* -------------------------------------------------------------------- */
6176
    /*      Does this layer even support attribute indexes?                 */
6177
    /* -------------------------------------------------------------------- */
6178
0
    if (poLayer->GetIndex() == nullptr)
6179
0
    {
6180
0
        CPLError(CE_Failure, CPLE_AppDefined,
6181
0
                 "CREATE INDEX ON not supported by this driver.");
6182
0
        CSLDestroy(papszTokens);
6183
0
        return OGRERR_FAILURE;
6184
0
    }
6185
6186
    /* -------------------------------------------------------------------- */
6187
    /*      Find the named field.                                           */
6188
    /* -------------------------------------------------------------------- */
6189
0
    int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6190
6191
0
    CSLDestroy(papszTokens);
6192
6193
0
    if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6194
0
    {
6195
0
        CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6196
0
                 pszSQLCommand);
6197
0
        return OGRERR_FAILURE;
6198
0
    }
6199
6200
    /* -------------------------------------------------------------------- */
6201
    /*      Attempt to create the index.                                    */
6202
    /* -------------------------------------------------------------------- */
6203
0
    OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
6204
0
    if (eErr == OGRERR_NONE)
6205
0
    {
6206
0
        eErr = poLayer->GetIndex()->IndexAllFeatures(i);
6207
0
    }
6208
0
    else
6209
0
    {
6210
0
        if (strlen(CPLGetLastErrorMsg()) == 0)
6211
0
            CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
6212
0
    }
6213
6214
0
    return eErr;
6215
0
}
6216
6217
/************************************************************************/
6218
/*                        ProcessSQLDropIndex()                         */
6219
/*                                                                      */
6220
/*      The correct syntax for dropping one or more indexes in          */
6221
/*      the OGR SQL dialect is:                                         */
6222
/*                                                                      */
6223
/*          DROP INDEX ON <layername> [USING <columnname>]              */
6224
/************************************************************************/
6225
6226
OGRErr GDALDataset::ProcessSQLDropIndex(const char *pszSQLCommand)
6227
6228
0
{
6229
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6230
6231
    /* -------------------------------------------------------------------- */
6232
    /*      Do some general syntax checking.                                */
6233
    /* -------------------------------------------------------------------- */
6234
0
    if ((CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) ||
6235
0
        !EQUAL(papszTokens[0], "DROP") || !EQUAL(papszTokens[1], "INDEX") ||
6236
0
        !EQUAL(papszTokens[2], "ON") ||
6237
0
        (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")))
6238
0
    {
6239
0
        CSLDestroy(papszTokens);
6240
0
        CPLError(CE_Failure, CPLE_AppDefined,
6241
0
                 "Syntax error in DROP INDEX command.\n"
6242
0
                 "Was '%s'\n"
6243
0
                 "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
6244
0
                 pszSQLCommand);
6245
0
        return OGRERR_FAILURE;
6246
0
    }
6247
6248
    /* -------------------------------------------------------------------- */
6249
    /*      Find the named layer.                                           */
6250
    /* -------------------------------------------------------------------- */
6251
0
    OGRLayer *poLayer = GetLayerByName(papszTokens[3]);
6252
0
    if (poLayer == nullptr)
6253
0
    {
6254
0
        CPLError(CE_Failure, CPLE_AppDefined,
6255
0
                 "DROP INDEX ON failed, no such layer as `%s'.",
6256
0
                 papszTokens[3]);
6257
0
        CSLDestroy(papszTokens);
6258
0
        return OGRERR_FAILURE;
6259
0
    }
6260
6261
    /* -------------------------------------------------------------------- */
6262
    /*      Does this layer even support attribute indexes?                 */
6263
    /* -------------------------------------------------------------------- */
6264
0
    if (poLayer->GetIndex() == nullptr)
6265
0
    {
6266
0
        CPLError(CE_Failure, CPLE_AppDefined,
6267
0
                 "Indexes not supported by this driver.");
6268
0
        CSLDestroy(papszTokens);
6269
0
        return OGRERR_FAILURE;
6270
0
    }
6271
6272
    /* -------------------------------------------------------------------- */
6273
    /*      If we were not given a field name, drop all indexes.            */
6274
    /* -------------------------------------------------------------------- */
6275
0
    if (CSLCount(papszTokens) == 4)
6276
0
    {
6277
0
        for (int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i)
6278
0
        {
6279
0
            OGRAttrIndex *poAttrIndex;
6280
6281
0
            poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
6282
0
            if (poAttrIndex != nullptr)
6283
0
            {
6284
0
                const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6285
0
                if (eErr != OGRERR_NONE)
6286
0
                {
6287
0
                    CSLDestroy(papszTokens);
6288
0
                    return eErr;
6289
0
                }
6290
0
            }
6291
0
        }
6292
6293
0
        CSLDestroy(papszTokens);
6294
0
        return OGRERR_NONE;
6295
0
    }
6296
6297
    /* -------------------------------------------------------------------- */
6298
    /*      Find the named field.                                           */
6299
    /* -------------------------------------------------------------------- */
6300
0
    int i = poLayer->GetLayerDefn()->GetFieldIndex(papszTokens[5]);
6301
0
    CSLDestroy(papszTokens);
6302
6303
0
    if (i >= poLayer->GetLayerDefn()->GetFieldCount())
6304
0
    {
6305
0
        CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
6306
0
                 pszSQLCommand);
6307
0
        return OGRERR_FAILURE;
6308
0
    }
6309
6310
    /* -------------------------------------------------------------------- */
6311
    /*      Attempt to drop the index.                                      */
6312
    /* -------------------------------------------------------------------- */
6313
0
    const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
6314
6315
0
    return eErr;
6316
0
}
6317
6318
/************************************************************************/
6319
/*                        ProcessSQLDropTable()                         */
6320
/*                                                                      */
6321
/*      The correct syntax for dropping a table (layer) in the OGR SQL  */
6322
/*      dialect is:                                                     */
6323
/*                                                                      */
6324
/*          DROP TABLE <layername>                                      */
6325
/************************************************************************/
6326
6327
OGRErr GDALDataset::ProcessSQLDropTable(const char *pszSQLCommand)
6328
6329
0
{
6330
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6331
6332
    /* -------------------------------------------------------------------- */
6333
    /*      Do some general syntax checking.                                */
6334
    /* -------------------------------------------------------------------- */
6335
0
    if (CSLCount(papszTokens) != 3 || !EQUAL(papszTokens[0], "DROP") ||
6336
0
        !EQUAL(papszTokens[1], "TABLE"))
6337
0
    {
6338
0
        CSLDestroy(papszTokens);
6339
0
        CPLError(CE_Failure, CPLE_AppDefined,
6340
0
                 "Syntax error in DROP TABLE command.\n"
6341
0
                 "Was '%s'\n"
6342
0
                 "Should be of form 'DROP TABLE <table>'",
6343
0
                 pszSQLCommand);
6344
0
        return OGRERR_FAILURE;
6345
0
    }
6346
6347
    /* -------------------------------------------------------------------- */
6348
    /*      Find the named layer.                                           */
6349
    /* -------------------------------------------------------------------- */
6350
0
    OGRLayer *poLayer = nullptr;
6351
6352
0
    int i = 0;  // Used after for.
6353
0
    for (; i < GetLayerCount(); ++i)
6354
0
    {
6355
0
        poLayer = GetLayer(i);
6356
6357
0
        if (poLayer != nullptr && EQUAL(poLayer->GetName(), papszTokens[2]))
6358
0
            break;
6359
0
        poLayer = nullptr;
6360
0
    }
6361
6362
0
    if (poLayer == nullptr)
6363
0
    {
6364
0
        CPLError(CE_Failure, CPLE_AppDefined,
6365
0
                 "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
6366
0
        CSLDestroy(papszTokens);
6367
0
        return OGRERR_FAILURE;
6368
0
    }
6369
6370
0
    CSLDestroy(papszTokens);
6371
6372
    /* -------------------------------------------------------------------- */
6373
    /*      Delete it.                                                      */
6374
    /* -------------------------------------------------------------------- */
6375
6376
0
    return DeleteLayer(i);
6377
0
}
6378
6379
//! @endcond
6380
6381
/************************************************************************/
6382
/*                    GDALDatasetParseSQLType()                       */
6383
/************************************************************************/
6384
6385
/* All arguments will be altered */
6386
static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
6387
                                            int &nPrecision)
6388
0
{
6389
0
    char *pszParenthesis = strchr(pszType, '(');
6390
0
    if (pszParenthesis)
6391
0
    {
6392
0
        nWidth = atoi(pszParenthesis + 1);
6393
0
        *pszParenthesis = '\0';
6394
0
        char *pszComma = strchr(pszParenthesis + 1, ',');
6395
0
        if (pszComma)
6396
0
            nPrecision = atoi(pszComma + 1);
6397
0
    }
6398
6399
0
    OGRFieldType eType = OFTString;
6400
0
    if (EQUAL(pszType, "INTEGER"))
6401
0
        eType = OFTInteger;
6402
0
    else if (EQUAL(pszType, "INTEGER[]"))
6403
0
        eType = OFTIntegerList;
6404
0
    else if (EQUAL(pszType, "FLOAT") || EQUAL(pszType, "NUMERIC") ||
6405
0
             EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
6406
0
             EQUAL(pszType, "REAL") /* unofficial alias */)
6407
0
        eType = OFTReal;
6408
0
    else if (EQUAL(pszType, "FLOAT[]") || EQUAL(pszType, "NUMERIC[]") ||
6409
0
             EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
6410
0
             EQUAL(pszType, "REAL[]") /* unofficial alias */)
6411
0
        eType = OFTRealList;
6412
0
    else if (EQUAL(pszType, "CHARACTER") ||
6413
0
             EQUAL(pszType, "TEXT") /* unofficial alias */ ||
6414
0
             EQUAL(pszType, "STRING") /* unofficial alias */ ||
6415
0
             EQUAL(pszType, "VARCHAR") /* unofficial alias */)
6416
0
        eType = OFTString;
6417
0
    else if (EQUAL(pszType, "TEXT[]") ||
6418
0
             EQUAL(pszType, "STRING[]") /* unofficial alias */ ||
6419
0
             EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
6420
0
        eType = OFTStringList;
6421
0
    else if (EQUAL(pszType, "DATE"))
6422
0
        eType = OFTDate;
6423
0
    else if (EQUAL(pszType, "TIME"))
6424
0
        eType = OFTTime;
6425
0
    else if (EQUAL(pszType, "TIMESTAMP") ||
6426
0
             EQUAL(pszType, "DATETIME") /* unofficial alias */)
6427
0
        eType = OFTDateTime;
6428
0
    else
6429
0
        CPLError(CE_Warning, CPLE_NotSupported,
6430
0
                 "Unsupported column type '%s'. Defaulting to VARCHAR",
6431
0
                 pszType);
6432
6433
0
    return eType;
6434
0
}
6435
6436
/************************************************************************/
6437
/*                    ProcessSQLAlterTableAddColumn()                   */
6438
/*                                                                      */
6439
/*      The correct syntax for adding a column in the OGR SQL           */
6440
/*      dialect is:                                                     */
6441
/*                                                                      */
6442
/*       ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
6443
/************************************************************************/
6444
6445
//! @cond Doxygen_Suppress
6446
OGRErr GDALDataset::ProcessSQLAlterTableAddColumn(const char *pszSQLCommand)
6447
6448
0
{
6449
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6450
6451
    /* -------------------------------------------------------------------- */
6452
    /*      Do some general syntax checking.                                */
6453
    /* -------------------------------------------------------------------- */
6454
0
    const char *pszLayerName = nullptr;
6455
0
    const char *pszColumnName = nullptr;
6456
0
    int iTypeIndex = 0;
6457
0
    const int nTokens = CSLCount(papszTokens);
6458
6459
0
    if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6460
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD") &&
6461
0
        EQUAL(papszTokens[4], "COLUMN"))
6462
0
    {
6463
0
        pszLayerName = papszTokens[2];
6464
0
        pszColumnName = papszTokens[5];
6465
0
        iTypeIndex = 6;
6466
0
    }
6467
0
    else if (nTokens >= 6 && EQUAL(papszTokens[0], "ALTER") &&
6468
0
             EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ADD"))
6469
0
    {
6470
0
        pszLayerName = papszTokens[2];
6471
0
        pszColumnName = papszTokens[4];
6472
0
        iTypeIndex = 5;
6473
0
    }
6474
0
    else
6475
0
    {
6476
0
        CSLDestroy(papszTokens);
6477
0
        CPLError(CE_Failure, CPLE_AppDefined,
6478
0
                 "Syntax error in ALTER TABLE ADD COLUMN command.\n"
6479
0
                 "Was '%s'\n"
6480
0
                 "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
6481
0
                 "<columnname> <columntype>'",
6482
0
                 pszSQLCommand);
6483
0
        return OGRERR_FAILURE;
6484
0
    }
6485
6486
    /* -------------------------------------------------------------------- */
6487
    /*      Merge type components into a single string if there were split  */
6488
    /*      with spaces                                                     */
6489
    /* -------------------------------------------------------------------- */
6490
0
    CPLString osType;
6491
0
    for (int i = iTypeIndex; i < nTokens; ++i)
6492
0
    {
6493
0
        osType += papszTokens[i];
6494
0
        CPLFree(papszTokens[i]);
6495
0
    }
6496
0
    char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6497
0
    papszTokens[iTypeIndex + 1] = nullptr;
6498
6499
    /* -------------------------------------------------------------------- */
6500
    /*      Find the named layer.                                           */
6501
    /* -------------------------------------------------------------------- */
6502
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6503
0
    if (poLayer == nullptr)
6504
0
    {
6505
0
        CPLError(CE_Failure, CPLE_AppDefined,
6506
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6507
0
                 pszLayerName);
6508
0
        CSLDestroy(papszTokens);
6509
0
        return OGRERR_FAILURE;
6510
0
    }
6511
6512
    /* -------------------------------------------------------------------- */
6513
    /*      Add column.                                                     */
6514
    /* -------------------------------------------------------------------- */
6515
6516
0
    int nWidth = 0;
6517
0
    int nPrecision = 0;
6518
0
    OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6519
0
    OGRFieldDefn oFieldDefn(pszColumnName, eType);
6520
0
    oFieldDefn.SetWidth(nWidth);
6521
0
    oFieldDefn.SetPrecision(nPrecision);
6522
6523
0
    CSLDestroy(papszTokens);
6524
6525
0
    return poLayer->CreateField(&oFieldDefn);
6526
0
}
6527
6528
/************************************************************************/
6529
/*                    ProcessSQLAlterTableDropColumn()                  */
6530
/*                                                                      */
6531
/*      The correct syntax for dropping a column in the OGR SQL         */
6532
/*      dialect is:                                                     */
6533
/*                                                                      */
6534
/*          ALTER TABLE <layername> DROP [COLUMN] <columnname>          */
6535
/************************************************************************/
6536
6537
OGRErr GDALDataset::ProcessSQLAlterTableDropColumn(const char *pszSQLCommand)
6538
6539
0
{
6540
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6541
6542
    /* -------------------------------------------------------------------- */
6543
    /*      Do some general syntax checking.                                */
6544
    /* -------------------------------------------------------------------- */
6545
0
    const char *pszLayerName = nullptr;
6546
0
    const char *pszColumnName = nullptr;
6547
0
    if (CSLCount(papszTokens) == 6 && EQUAL(papszTokens[0], "ALTER") &&
6548
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP") &&
6549
0
        EQUAL(papszTokens[4], "COLUMN"))
6550
0
    {
6551
0
        pszLayerName = papszTokens[2];
6552
0
        pszColumnName = papszTokens[5];
6553
0
    }
6554
0
    else if (CSLCount(papszTokens) == 5 && EQUAL(papszTokens[0], "ALTER") &&
6555
0
             EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "DROP"))
6556
0
    {
6557
0
        pszLayerName = papszTokens[2];
6558
0
        pszColumnName = papszTokens[4];
6559
0
    }
6560
0
    else
6561
0
    {
6562
0
        CSLDestroy(papszTokens);
6563
0
        CPLError(CE_Failure, CPLE_AppDefined,
6564
0
                 "Syntax error in ALTER TABLE DROP COLUMN command.\n"
6565
0
                 "Was '%s'\n"
6566
0
                 "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
6567
0
                 "<columnname>'",
6568
0
                 pszSQLCommand);
6569
0
        return OGRERR_FAILURE;
6570
0
    }
6571
6572
    /* -------------------------------------------------------------------- */
6573
    /*      Find the named layer.                                           */
6574
    /* -------------------------------------------------------------------- */
6575
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6576
0
    if (poLayer == nullptr)
6577
0
    {
6578
0
        CPLError(CE_Failure, CPLE_AppDefined,
6579
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6580
0
                 pszLayerName);
6581
0
        CSLDestroy(papszTokens);
6582
0
        return OGRERR_FAILURE;
6583
0
    }
6584
6585
    /* -------------------------------------------------------------------- */
6586
    /*      Find the field.                                                 */
6587
    /* -------------------------------------------------------------------- */
6588
6589
0
    int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6590
0
    if (nFieldIndex < 0)
6591
0
    {
6592
0
        CPLError(CE_Failure, CPLE_AppDefined,
6593
0
                 "%s failed, no such field as `%s'.", pszSQLCommand,
6594
0
                 pszColumnName);
6595
0
        CSLDestroy(papszTokens);
6596
0
        return OGRERR_FAILURE;
6597
0
    }
6598
6599
    /* -------------------------------------------------------------------- */
6600
    /*      Remove it.                                                      */
6601
    /* -------------------------------------------------------------------- */
6602
6603
0
    CSLDestroy(papszTokens);
6604
6605
0
    return poLayer->DeleteField(nFieldIndex);
6606
0
}
6607
6608
/************************************************************************/
6609
/*                 ProcessSQLAlterTableRenameColumn()                   */
6610
/*                                                                      */
6611
/*      The correct syntax for renaming a column in the OGR SQL         */
6612
/*      dialect is:                                                     */
6613
/*                                                                      */
6614
/*       ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
6615
/************************************************************************/
6616
6617
OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn(const char *pszSQLCommand)
6618
6619
0
{
6620
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6621
6622
    /* -------------------------------------------------------------------- */
6623
    /*      Do some general syntax checking.                                */
6624
    /* -------------------------------------------------------------------- */
6625
0
    const char *pszLayerName = nullptr;
6626
0
    const char *pszOldColName = nullptr;
6627
0
    const char *pszNewColName = nullptr;
6628
0
    if (CSLCount(papszTokens) == 8 && EQUAL(papszTokens[0], "ALTER") &&
6629
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "RENAME") &&
6630
0
        EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TO"))
6631
0
    {
6632
0
        pszLayerName = papszTokens[2];
6633
0
        pszOldColName = papszTokens[5];
6634
0
        pszNewColName = papszTokens[7];
6635
0
    }
6636
0
    else if (CSLCount(papszTokens) == 7 && EQUAL(papszTokens[0], "ALTER") &&
6637
0
             EQUAL(papszTokens[1], "TABLE") &&
6638
0
             EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[5], "TO"))
6639
0
    {
6640
0
        pszLayerName = papszTokens[2];
6641
0
        pszOldColName = papszTokens[4];
6642
0
        pszNewColName = papszTokens[6];
6643
0
    }
6644
0
    else
6645
0
    {
6646
0
        CSLDestroy(papszTokens);
6647
0
        CPLError(CE_Failure, CPLE_AppDefined,
6648
0
                 "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
6649
0
                 "Was '%s'\n"
6650
0
                 "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
6651
0
                 "<columnname> TO <newname>'",
6652
0
                 pszSQLCommand);
6653
0
        return OGRERR_FAILURE;
6654
0
    }
6655
6656
    /* -------------------------------------------------------------------- */
6657
    /*      Find the named layer.                                           */
6658
    /* -------------------------------------------------------------------- */
6659
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6660
0
    if (poLayer == nullptr)
6661
0
    {
6662
0
        CPLError(CE_Failure, CPLE_AppDefined,
6663
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6664
0
                 pszLayerName);
6665
0
        CSLDestroy(papszTokens);
6666
0
        return OGRERR_FAILURE;
6667
0
    }
6668
6669
    /* -------------------------------------------------------------------- */
6670
    /*      Find the field.                                                 */
6671
    /* -------------------------------------------------------------------- */
6672
6673
0
    const int nFieldIndex =
6674
0
        poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
6675
0
    if (nFieldIndex < 0)
6676
0
    {
6677
0
        CPLError(CE_Failure, CPLE_AppDefined,
6678
0
                 "%s failed, no such field as `%s'.", pszSQLCommand,
6679
0
                 pszOldColName);
6680
0
        CSLDestroy(papszTokens);
6681
0
        return OGRERR_FAILURE;
6682
0
    }
6683
6684
    /* -------------------------------------------------------------------- */
6685
    /*      Rename column.                                                  */
6686
    /* -------------------------------------------------------------------- */
6687
0
    OGRFieldDefn *poOldFieldDefn =
6688
0
        poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6689
0
    OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6690
0
    oNewFieldDefn.SetName(pszNewColName);
6691
6692
0
    CSLDestroy(papszTokens);
6693
6694
0
    return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
6695
0
                                   ALTER_NAME_FLAG);
6696
0
}
6697
6698
/************************************************************************/
6699
/*                 ProcessSQLAlterTableAlterColumn()                    */
6700
/*                                                                      */
6701
/*      The correct syntax for altering the type of a column in the     */
6702
/*      OGR SQL dialect is:                                             */
6703
/*                                                                      */
6704
/*   ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
6705
/************************************************************************/
6706
6707
OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn(const char *pszSQLCommand)
6708
6709
0
{
6710
0
    char **papszTokens = CSLTokenizeString(pszSQLCommand);
6711
6712
    /* -------------------------------------------------------------------- */
6713
    /*      Do some general syntax checking.                                */
6714
    /* -------------------------------------------------------------------- */
6715
0
    const char *pszLayerName = nullptr;
6716
0
    const char *pszColumnName = nullptr;
6717
0
    int iTypeIndex = 0;
6718
0
    const int nTokens = CSLCount(papszTokens);
6719
6720
0
    if (nTokens >= 8 && EQUAL(papszTokens[0], "ALTER") &&
6721
0
        EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6722
0
        EQUAL(papszTokens[4], "COLUMN") && EQUAL(papszTokens[6], "TYPE"))
6723
0
    {
6724
0
        pszLayerName = papszTokens[2];
6725
0
        pszColumnName = papszTokens[5];
6726
0
        iTypeIndex = 7;
6727
0
    }
6728
0
    else if (nTokens >= 7 && EQUAL(papszTokens[0], "ALTER") &&
6729
0
             EQUAL(papszTokens[1], "TABLE") && EQUAL(papszTokens[3], "ALTER") &&
6730
0
             EQUAL(papszTokens[5], "TYPE"))
6731
0
    {
6732
0
        pszLayerName = papszTokens[2];
6733
0
        pszColumnName = papszTokens[4];
6734
0
        iTypeIndex = 6;
6735
0
    }
6736
0
    else
6737
0
    {
6738
0
        CSLDestroy(papszTokens);
6739
0
        CPLError(CE_Failure, CPLE_AppDefined,
6740
0
                 "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
6741
0
                 "Was '%s'\n"
6742
0
                 "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
6743
0
                 "<columnname> TYPE <columntype>'",
6744
0
                 pszSQLCommand);
6745
0
        return OGRERR_FAILURE;
6746
0
    }
6747
6748
    /* -------------------------------------------------------------------- */
6749
    /*      Merge type components into a single string if there were split  */
6750
    /*      with spaces                                                     */
6751
    /* -------------------------------------------------------------------- */
6752
0
    CPLString osType;
6753
0
    for (int i = iTypeIndex; i < nTokens; ++i)
6754
0
    {
6755
0
        osType += papszTokens[i];
6756
0
        CPLFree(papszTokens[i]);
6757
0
    }
6758
0
    char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
6759
0
    papszTokens[iTypeIndex + 1] = nullptr;
6760
6761
    /* -------------------------------------------------------------------- */
6762
    /*      Find the named layer.                                           */
6763
    /* -------------------------------------------------------------------- */
6764
0
    OGRLayer *poLayer = GetLayerByName(pszLayerName);
6765
0
    if (poLayer == nullptr)
6766
0
    {
6767
0
        CPLError(CE_Failure, CPLE_AppDefined,
6768
0
                 "%s failed, no such layer as `%s'.", pszSQLCommand,
6769
0
                 pszLayerName);
6770
0
        CSLDestroy(papszTokens);
6771
0
        return OGRERR_FAILURE;
6772
0
    }
6773
6774
    /* -------------------------------------------------------------------- */
6775
    /*      Find the field.                                                 */
6776
    /* -------------------------------------------------------------------- */
6777
6778
0
    const int nFieldIndex =
6779
0
        poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
6780
0
    if (nFieldIndex < 0)
6781
0
    {
6782
0
        CPLError(CE_Failure, CPLE_AppDefined,
6783
0
                 "%s failed, no such field as `%s'.", pszSQLCommand,
6784
0
                 pszColumnName);
6785
0
        CSLDestroy(papszTokens);
6786
0
        return OGRERR_FAILURE;
6787
0
    }
6788
6789
    /* -------------------------------------------------------------------- */
6790
    /*      Alter column.                                                   */
6791
    /* -------------------------------------------------------------------- */
6792
6793
0
    OGRFieldDefn *poOldFieldDefn =
6794
0
        poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
6795
0
    OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
6796
6797
0
    int nWidth = 0;
6798
0
    int nPrecision = 0;
6799
0
    OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
6800
0
    oNewFieldDefn.SetType(eType);
6801
0
    oNewFieldDefn.SetWidth(nWidth);
6802
0
    oNewFieldDefn.SetPrecision(nPrecision);
6803
6804
0
    int l_nFlags = 0;
6805
0
    if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
6806
0
        l_nFlags |= ALTER_TYPE_FLAG;
6807
0
    if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
6808
0
        poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
6809
0
        l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
6810
6811
0
    CSLDestroy(papszTokens);
6812
6813
0
    if (l_nFlags == 0)
6814
0
        return OGRERR_NONE;
6815
6816
0
    return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
6817
0
}
6818
6819
//! @endcond
6820
6821
/************************************************************************/
6822
/*                             ExecuteSQL()                             */
6823
/************************************************************************/
6824
6825
/**
6826
 \brief Execute an SQL statement against the data store.
6827
6828
 The result of an SQL query is either NULL for statements that are in error,
6829
 or that have no results set, or an OGRLayer pointer representing a results
6830
 set from the query.  Note that this OGRLayer is in addition to the layers
6831
 in the data store and must be destroyed with
6832
 ReleaseResultSet() before the dataset is closed
6833
 (destroyed).
6834
6835
 This method is the same as the C function GDALDatasetExecuteSQL() and the
6836
 deprecated OGR_DS_ExecuteSQL().
6837
6838
 For more information on the SQL dialect supported internally by OGR
6839
 review the <a href="https://gdal.org/user/ogr_sql_dialect.html">OGR SQL</a>
6840
 document.  Some drivers (i.e. Oracle and PostGIS) pass the SQL directly through
6841
 to the underlying RDBMS.
6842
6843
 Starting with OGR 1.10, the <a
6844
 href="https://gdal.org/user/sql_sqlite_dialect.html">SQLITE dialect</a> can
6845
 also be used.
6846
6847
 In GDAL 1.X, this method used to be in the OGRDataSource class.
6848
6849
 @param pszStatement the SQL statement to execute.
6850
 @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
6851
 @param pszDialect allows control of the statement dialect. If set to NULL, the
6852
 OGR SQL engine will be used, except for RDBMS drivers that will use their
6853
 dedicated SQL engine, unless OGRSQL is explicitly passed as the
6854
 dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
6855
6856
 @return an OGRLayer containing the results of the query.  Deallocate with
6857
 ReleaseResultSet().
6858
6859
*/
6860
6861
OGRLayer *GDALDataset::ExecuteSQL(const char *pszStatement,
6862
                                  OGRGeometry *poSpatialFilter,
6863
                                  const char *pszDialect)
6864
6865
0
{
6866
0
    return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, nullptr);
6867
0
}
6868
6869
//! @cond Doxygen_Suppress
6870
OGRLayer *
6871
GDALDataset::ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
6872
                        const char *pszDialect,
6873
                        swq_select_parse_options *poSelectParseOptions)
6874
6875
0
{
6876
0
    if (pszDialect != nullptr && EQUAL(pszDialect, "SQLite"))
6877
0
    {
6878
#ifdef SQLITE_ENABLED
6879
        return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
6880
                                   pszDialect);
6881
#else
6882
0
        CPLError(CE_Failure, CPLE_NotSupported,
6883
0
                 "The SQLite driver needs to be compiled to support the "
6884
0
                 "SQLite SQL dialect");
6885
0
        return nullptr;
6886
0
#endif
6887
0
    }
6888
6889
0
    if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
6890
0
        !EQUAL(pszDialect, "OGRSQL"))
6891
0
    {
6892
0
        std::string osDialectList = "'OGRSQL'";
6893
#ifdef SQLITE_ENABLED
6894
        osDialectList += ", 'SQLITE'";
6895
#endif
6896
0
        const char *pszDialects =
6897
0
            GetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS);
6898
0
        if (pszDialects)
6899
0
        {
6900
0
            const CPLStringList aosTokens(
6901
0
                CSLTokenizeString2(pszDialects, " ", 0));
6902
0
            for (int i = 0; i < aosTokens.size(); ++i)
6903
0
            {
6904
0
                if (!EQUAL(aosTokens[i], "OGRSQL") &&
6905
0
                    !EQUAL(aosTokens[i], "SQLITE"))
6906
0
                {
6907
0
                    osDialectList += ", '";
6908
0
                    osDialectList += aosTokens[i];
6909
0
                    osDialectList += "'";
6910
0
                }
6911
0
            }
6912
0
        }
6913
0
        CPLError(CE_Warning, CPLE_NotSupported,
6914
0
                 "Dialect '%s' is unsupported. Only supported dialects are %s. "
6915
0
                 "Defaulting to OGRSQL",
6916
0
                 pszDialect, osDialectList.c_str());
6917
0
    }
6918
6919
    /* -------------------------------------------------------------------- */
6920
    /*      Handle CREATE INDEX statements specially.                       */
6921
    /* -------------------------------------------------------------------- */
6922
0
    if (STARTS_WITH_CI(pszStatement, "CREATE INDEX"))
6923
0
    {
6924
0
        ProcessSQLCreateIndex(pszStatement);
6925
0
        return nullptr;
6926
0
    }
6927
6928
    /* -------------------------------------------------------------------- */
6929
    /*      Handle DROP INDEX statements specially.                         */
6930
    /* -------------------------------------------------------------------- */
6931
0
    if (STARTS_WITH_CI(pszStatement, "DROP INDEX"))
6932
0
    {
6933
0
        ProcessSQLDropIndex(pszStatement);
6934
0
        return nullptr;
6935
0
    }
6936
6937
    /* -------------------------------------------------------------------- */
6938
    /*      Handle DROP TABLE statements specially.                         */
6939
    /* -------------------------------------------------------------------- */
6940
0
    if (STARTS_WITH_CI(pszStatement, "DROP TABLE"))
6941
0
    {
6942
0
        ProcessSQLDropTable(pszStatement);
6943
0
        return nullptr;
6944
0
    }
6945
6946
    /* -------------------------------------------------------------------- */
6947
    /*      Handle ALTER TABLE statements specially.                        */
6948
    /* -------------------------------------------------------------------- */
6949
0
    if (STARTS_WITH_CI(pszStatement, "ALTER TABLE"))
6950
0
    {
6951
0
        char **papszTokens = CSLTokenizeString(pszStatement);
6952
0
        const int nTokens = CSLCount(papszTokens);
6953
0
        if (nTokens >= 4 && EQUAL(papszTokens[3], "ADD"))
6954
0
        {
6955
0
            ProcessSQLAlterTableAddColumn(pszStatement);
6956
0
            CSLDestroy(papszTokens);
6957
0
            return nullptr;
6958
0
        }
6959
0
        else if (nTokens >= 4 && EQUAL(papszTokens[3], "DROP"))
6960
0
        {
6961
0
            ProcessSQLAlterTableDropColumn(pszStatement);
6962
0
            CSLDestroy(papszTokens);
6963
0
            return nullptr;
6964
0
        }
6965
0
        else if (nTokens == 6 && EQUAL(papszTokens[3], "RENAME") &&
6966
0
                 EQUAL(papszTokens[4], "TO"))
6967
0
        {
6968
0
            const char *pszSrcTableName = papszTokens[2];
6969
0
            const char *pszDstTableName = papszTokens[5];
6970
0
            auto poSrcLayer = GetLayerByName(pszSrcTableName);
6971
0
            if (poSrcLayer)
6972
0
            {
6973
0
                CPL_IGNORE_RET_VAL(poSrcLayer->Rename(pszDstTableName));
6974
0
            }
6975
0
            else
6976
0
            {
6977
0
                CPLError(CE_Failure, CPLE_AppDefined, "Invalid layer name");
6978
0
            }
6979
0
            CSLDestroy(papszTokens);
6980
0
            return nullptr;
6981
0
        }
6982
0
        else if (nTokens >= 4 && EQUAL(papszTokens[3], "RENAME"))
6983
0
        {
6984
0
            ProcessSQLAlterTableRenameColumn(pszStatement);
6985
0
            CSLDestroy(papszTokens);
6986
0
            return nullptr;
6987
0
        }
6988
0
        else if (nTokens >= 4 && EQUAL(papszTokens[3], "ALTER"))
6989
0
        {
6990
0
            ProcessSQLAlterTableAlterColumn(pszStatement);
6991
0
            CSLDestroy(papszTokens);
6992
0
            return nullptr;
6993
0
        }
6994
0
        else
6995
0
        {
6996
0
            CPLError(CE_Failure, CPLE_AppDefined,
6997
0
                     "Unsupported ALTER TABLE command : %s", pszStatement);
6998
0
            CSLDestroy(papszTokens);
6999
0
            return nullptr;
7000
0
        }
7001
0
    }
7002
7003
    /* -------------------------------------------------------------------- */
7004
    /*      Preparse the SQL statement.                                     */
7005
    /* -------------------------------------------------------------------- */
7006
0
    swq_select *psSelectInfo = new swq_select();
7007
0
    swq_custom_func_registrar *poCustomFuncRegistrar = nullptr;
7008
0
    if (poSelectParseOptions != nullptr)
7009
0
        poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
7010
0
    if (psSelectInfo->preparse(pszStatement,
7011
0
                               poCustomFuncRegistrar != nullptr) != CE_None)
7012
0
    {
7013
0
        delete psSelectInfo;
7014
0
        return nullptr;
7015
0
    }
7016
7017
    /* -------------------------------------------------------------------- */
7018
    /*      If there is no UNION ALL, build result layer.                   */
7019
    /* -------------------------------------------------------------------- */
7020
0
    if (psSelectInfo->poOtherSelect == nullptr)
7021
0
    {
7022
0
        return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
7023
0
                                        pszDialect, poSelectParseOptions);
7024
0
    }
7025
7026
    /* -------------------------------------------------------------------- */
7027
    /*      Build result union layer.                                       */
7028
    /* -------------------------------------------------------------------- */
7029
0
    int nSrcLayers = 0;
7030
0
    OGRLayer **papoSrcLayers = nullptr;
7031
7032
0
    do
7033
0
    {
7034
0
        swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
7035
0
        psSelectInfo->poOtherSelect = nullptr;
7036
7037
0
        OGRLayer *poLayer = BuildLayerFromSelectInfo(
7038
0
            psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
7039
0
        if (poLayer == nullptr)
7040
0
        {
7041
            // Each source layer owns an independent select info.
7042
0
            for (int i = 0; i < nSrcLayers; ++i)
7043
0
                delete papoSrcLayers[i];
7044
0
            CPLFree(papoSrcLayers);
7045
7046
            // So we just have to destroy the remaining select info.
7047
0
            delete psNextSelectInfo;
7048
7049
0
            return nullptr;
7050
0
        }
7051
0
        else
7052
0
        {
7053
0
            papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
7054
0
                papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
7055
0
            papoSrcLayers[nSrcLayers] = poLayer;
7056
0
            ++nSrcLayers;
7057
7058
0
            psSelectInfo = psNextSelectInfo;
7059
0
        }
7060
0
    } while (psSelectInfo != nullptr);
7061
7062
0
    return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
7063
0
}
7064
7065
//! @endcond
7066
7067
/************************************************************************/
7068
/*                             AbortSQL()                             */
7069
/************************************************************************/
7070
7071
/**
7072
 \brief Abort any SQL statement running in the data store.
7073
7074
 This function can be safely called from any thread (pending that the dataset
7075
 object is still alive). Driver implementations will make sure that it can be
7076
 called in a thread-safe way.
7077
7078
 This might not be implemented by all drivers. At time of writing, only SQLite,
7079
 GPKG and PG drivers implement it
7080
7081
 This method is the same as the C method GDALDatasetAbortSQL()
7082
7083
 @since GDAL 3.2.0
7084
7085
7086
*/
7087
7088
OGRErr GDALDataset::AbortSQL()
7089
0
{
7090
0
    CPLError(CE_Failure, CPLE_NotSupported,
7091
0
             "AbortSQL is not supported for this driver.");
7092
0
    return OGRERR_UNSUPPORTED_OPERATION;
7093
0
}
7094
7095
/************************************************************************/
7096
/*                        BuildLayerFromSelectInfo()                    */
7097
/************************************************************************/
7098
7099
struct GDALSQLParseInfo
7100
{
7101
    swq_field_list sFieldList;
7102
    int nExtraDSCount;
7103
    GDALDataset **papoExtraDS;
7104
    char *pszWHERE;
7105
};
7106
7107
OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
7108
    swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
7109
    const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
7110
0
{
7111
0
    std::unique_ptr<swq_select> psSelectInfoUnique(psSelectInfo);
7112
7113
0
    std::unique_ptr<OGRGenSQLResultsLayer> poResults;
7114
0
    GDALSQLParseInfo *psParseInfo =
7115
0
        BuildParseInfo(psSelectInfoUnique.get(), poSelectParseOptions);
7116
7117
0
    if (psParseInfo)
7118
0
    {
7119
0
        const auto nErrorCounter = CPLGetErrorCounter();
7120
0
        poResults = std::make_unique<OGRGenSQLResultsLayer>(
7121
0
            this, std::move(psSelectInfoUnique), poSpatialFilter,
7122
0
            psParseInfo->pszWHERE, pszDialect);
7123
0
        if (CPLGetErrorCounter() > nErrorCounter &&
7124
0
            CPLGetLastErrorType() != CE_None)
7125
0
            poResults.reset();
7126
0
    }
7127
7128
0
    DestroyParseInfo(psParseInfo);
7129
7130
0
    return poResults.release();
7131
0
}
7132
7133
/************************************************************************/
7134
/*                             DestroyParseInfo()                       */
7135
/************************************************************************/
7136
7137
//! @cond Doxygen_Suppress
7138
void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
7139
0
{
7140
0
    if (psParseInfo == nullptr)
7141
0
        return;
7142
7143
0
    CPLFree(psParseInfo->sFieldList.names);
7144
0
    CPLFree(psParseInfo->sFieldList.types);
7145
0
    CPLFree(psParseInfo->sFieldList.table_ids);
7146
0
    CPLFree(psParseInfo->sFieldList.ids);
7147
7148
    // Release the datasets we have opened with OGROpenShared()
7149
    // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
7150
    // has taken a reference on them, which it will release in its
7151
    // destructor.
7152
0
    for (int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS)
7153
0
        GDALClose(psParseInfo->papoExtraDS[iEDS]);
7154
7155
0
    CPLFree(psParseInfo->papoExtraDS);
7156
0
    CPLFree(psParseInfo->pszWHERE);
7157
0
    CPLFree(psParseInfo);
7158
0
}
7159
7160
/************************************************************************/
7161
/*                            BuildParseInfo()                          */
7162
/************************************************************************/
7163
7164
GDALSQLParseInfo *
7165
GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
7166
                            swq_select_parse_options *poSelectParseOptions)
7167
0
{
7168
0
    int nFirstLayerFirstSpecialFieldIndex = 0;
7169
7170
0
    GDALSQLParseInfo *psParseInfo =
7171
0
        static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
7172
7173
    /* -------------------------------------------------------------------- */
7174
    /*      Validate that all the source tables are recognized, count       */
7175
    /*      fields.                                                         */
7176
    /* -------------------------------------------------------------------- */
7177
0
    int nFieldCount = 0;
7178
7179
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7180
0
    {
7181
0
        swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7182
0
        GDALDataset *poTableDS = this;
7183
7184
0
        if (psTableDef->data_source != nullptr)
7185
0
        {
7186
0
            poTableDS = GDALDataset::FromHandle(
7187
0
                OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7188
0
            if (poTableDS == nullptr)
7189
0
            {
7190
0
                if (strlen(CPLGetLastErrorMsg()) == 0)
7191
0
                    CPLError(CE_Failure, CPLE_AppDefined,
7192
0
                             "Unable to open secondary datasource "
7193
0
                             "`%s' required by JOIN.",
7194
0
                             psTableDef->data_source);
7195
7196
0
                DestroyParseInfo(psParseInfo);
7197
0
                return nullptr;
7198
0
            }
7199
7200
            // Keep in an array to release at the end of this function.
7201
0
            psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
7202
0
                psParseInfo->papoExtraDS,
7203
0
                sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
7204
0
            psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
7205
0
        }
7206
7207
0
        OGRLayer *poSrcLayer =
7208
0
            poTableDS->GetLayerByName(psTableDef->table_name);
7209
7210
0
        if (poSrcLayer == nullptr)
7211
0
        {
7212
0
            CPLError(CE_Failure, CPLE_AppDefined,
7213
0
                     "SELECT from table %s failed, no such table/featureclass.",
7214
0
                     psTableDef->table_name);
7215
7216
0
            DestroyParseInfo(psParseInfo);
7217
0
            return nullptr;
7218
0
        }
7219
7220
0
        nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
7221
0
        if (iTable == 0 ||
7222
0
            (poSelectParseOptions &&
7223
0
             poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7224
0
            nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7225
7226
0
        const char *pszFID = poSrcLayer->GetFIDColumn();
7227
0
        if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7228
0
            poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7229
0
            nFieldCount++;
7230
0
    }
7231
7232
    /* -------------------------------------------------------------------- */
7233
    /*      Build the field list for all indicated tables.                  */
7234
    /* -------------------------------------------------------------------- */
7235
7236
0
    psParseInfo->sFieldList.table_count = psSelectInfo->table_count;
7237
0
    psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
7238
7239
0
    psParseInfo->sFieldList.count = 0;
7240
0
    psParseInfo->sFieldList.names = static_cast<char **>(
7241
0
        CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7242
0
    psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
7243
0
        sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7244
0
    psParseInfo->sFieldList.table_ids = static_cast<int *>(
7245
0
        CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7246
0
    psParseInfo->sFieldList.ids = static_cast<int *>(
7247
0
        CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
7248
7249
0
    bool bIsFID64 = false;
7250
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7251
0
    {
7252
0
        swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7253
0
        GDALDataset *poTableDS = this;
7254
7255
0
        if (psTableDef->data_source != nullptr)
7256
0
        {
7257
0
            poTableDS = GDALDataset::FromHandle(
7258
0
                OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7259
0
            CPLAssert(poTableDS != nullptr);
7260
0
            poTableDS->Dereference();
7261
0
        }
7262
7263
0
        OGRLayer *poSrcLayer =
7264
0
            poTableDS->GetLayerByName(psTableDef->table_name);
7265
7266
0
        for (int iField = 0;
7267
0
             iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++)
7268
0
        {
7269
0
            OGRFieldDefn *poFDefn =
7270
0
                poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
7271
0
            const int iOutField = psParseInfo->sFieldList.count++;
7272
0
            psParseInfo->sFieldList.names[iOutField] =
7273
0
                const_cast<char *>(poFDefn->GetNameRef());
7274
0
            if (poFDefn->GetType() == OFTInteger)
7275
0
            {
7276
0
                if (poFDefn->GetSubType() == OFSTBoolean)
7277
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7278
0
                else
7279
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7280
0
            }
7281
0
            else if (poFDefn->GetType() == OFTInteger64)
7282
0
            {
7283
0
                if (poFDefn->GetSubType() == OFSTBoolean)
7284
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_BOOLEAN;
7285
0
                else
7286
0
                    psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7287
0
            }
7288
0
            else if (poFDefn->GetType() == OFTReal)
7289
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_FLOAT;
7290
0
            else if (poFDefn->GetType() == OFTString)
7291
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_STRING;
7292
0
            else if (poFDefn->GetType() == OFTTime)
7293
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_TIME;
7294
0
            else if (poFDefn->GetType() == OFTDate)
7295
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_DATE;
7296
0
            else if (poFDefn->GetType() == OFTDateTime)
7297
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_TIMESTAMP;
7298
0
            else
7299
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_OTHER;
7300
7301
0
            psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7302
0
            psParseInfo->sFieldList.ids[iOutField] = iField;
7303
0
        }
7304
7305
0
        if (iTable == 0)
7306
0
        {
7307
0
            nFirstLayerFirstSpecialFieldIndex = psParseInfo->sFieldList.count;
7308
0
        }
7309
7310
0
        if (iTable == 0 ||
7311
0
            (poSelectParseOptions &&
7312
0
             poSelectParseOptions->bAddSecondaryTablesGeometryFields))
7313
0
        {
7314
7315
0
            for (int iField = 0;
7316
0
                 iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
7317
0
                 iField++)
7318
0
            {
7319
0
                OGRGeomFieldDefn *poFDefn =
7320
0
                    poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
7321
0
                const int iOutField = psParseInfo->sFieldList.count++;
7322
0
                psParseInfo->sFieldList.names[iOutField] =
7323
0
                    const_cast<char *>(poFDefn->GetNameRef());
7324
0
                if (*psParseInfo->sFieldList.names[iOutField] == '\0')
7325
0
                    psParseInfo->sFieldList.names[iOutField] =
7326
0
                        const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
7327
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
7328
7329
0
                psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7330
0
                psParseInfo->sFieldList.ids[iOutField] =
7331
0
                    GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
7332
0
                        poSrcLayer->GetLayerDefn(), iField);
7333
0
            }
7334
0
        }
7335
7336
0
        if (iTable == 0 && poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7337
0
            EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7338
0
        {
7339
0
            bIsFID64 = true;
7340
0
        }
7341
0
    }
7342
7343
    /* -------------------------------------------------------------------- */
7344
    /*      Expand '*' in 'SELECT *' now before we add the pseudo fields    */
7345
    /* -------------------------------------------------------------------- */
7346
0
    const bool bAlwaysPrefixWithTableName =
7347
0
        poSelectParseOptions &&
7348
0
        poSelectParseOptions->bAlwaysPrefixWithTableName;
7349
0
    if (psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
7350
0
                                      bAlwaysPrefixWithTableName) != CE_None)
7351
0
    {
7352
0
        DestroyParseInfo(psParseInfo);
7353
0
        return nullptr;
7354
0
    }
7355
7356
0
    for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
7357
0
    {
7358
0
        psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
7359
0
            const_cast<char *>(SpecialFieldNames[iField]);
7360
0
        psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
7361
0
            (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
7362
0
                                            : SpecialFieldTypes[iField];
7363
0
        psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
7364
0
        psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
7365
0
            nFirstLayerFirstSpecialFieldIndex + iField;
7366
0
        psParseInfo->sFieldList.count++;
7367
0
    }
7368
7369
    /* In the case a layer has an explicit FID column name, then add it */
7370
    /* so it can be selected */
7371
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
7372
0
    {
7373
0
        swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
7374
0
        GDALDataset *poTableDS = this;
7375
7376
0
        if (psTableDef->data_source != nullptr)
7377
0
        {
7378
0
            poTableDS = GDALDataset::FromHandle(
7379
0
                OGROpenShared(psTableDef->data_source, FALSE, nullptr));
7380
0
            CPLAssert(poTableDS != nullptr);
7381
0
            poTableDS->Dereference();
7382
0
        }
7383
7384
0
        OGRLayer *poSrcLayer =
7385
0
            poTableDS->GetLayerByName(psTableDef->table_name);
7386
7387
0
        const char *pszFID = poSrcLayer->GetFIDColumn();
7388
0
        if (pszFID && !EQUAL(pszFID, "") && !EQUAL(pszFID, "FID") &&
7389
0
            poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFID) < 0)
7390
0
        {
7391
0
            const int iOutField = psParseInfo->sFieldList.count++;
7392
0
            psParseInfo->sFieldList.names[iOutField] =
7393
0
                const_cast<char *>(pszFID);
7394
0
            if (poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
7395
0
                EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
7396
0
            {
7397
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER64;
7398
0
            }
7399
0
            else
7400
0
            {
7401
0
                psParseInfo->sFieldList.types[iOutField] = SWQ_INTEGER;
7402
0
            }
7403
0
            psParseInfo->sFieldList.table_ids[iOutField] = iTable;
7404
0
            psParseInfo->sFieldList.ids[iOutField] =
7405
0
                poSrcLayer->GetLayerDefn()->GetFieldCount() + SPF_FID;
7406
0
        }
7407
0
    }
7408
7409
    /* -------------------------------------------------------------------- */
7410
    /*      Finish the parse operation.                                     */
7411
    /* -------------------------------------------------------------------- */
7412
0
    if (psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
7413
0
        CE_None)
7414
0
    {
7415
0
        DestroyParseInfo(psParseInfo);
7416
0
        return nullptr;
7417
0
    }
7418
7419
    /* -------------------------------------------------------------------- */
7420
    /*      Extract the WHERE expression to use separately.                 */
7421
    /* -------------------------------------------------------------------- */
7422
0
    if (psSelectInfo->where_expr != nullptr)
7423
0
    {
7424
0
        psParseInfo->pszWHERE =
7425
0
            psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
7426
        // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
7427
0
    }
7428
7429
0
    return psParseInfo;
7430
0
}
7431
7432
//! @endcond
7433
7434
/************************************************************************/
7435
/*                          ReleaseResultSet()                          */
7436
/************************************************************************/
7437
7438
/**
7439
 \brief Release results of ExecuteSQL().
7440
7441
 This method should only be used to deallocate OGRLayers resulting from
7442
 an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
7443
 results set before destroying the GDALDataset may cause errors.
7444
7445
 This method is the same as the C function GDALDatasetReleaseResultSet() and the
7446
 deprecated OGR_DS_ReleaseResultSet().
7447
7448
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7449
7450
 @param poResultsSet the result of a previous ExecuteSQL() call.
7451
*/
7452
7453
void GDALDataset::ReleaseResultSet(OGRLayer *poResultsSet)
7454
7455
0
{
7456
0
    delete poResultsSet;
7457
0
}
7458
7459
/************************************************************************/
7460
/*                            GetStyleTable()                           */
7461
/************************************************************************/
7462
7463
/**
7464
 \brief Returns dataset style table.
7465
7466
 This method is the same as the C function GDALDatasetGetStyleTable() and the
7467
 deprecated OGR_DS_GetStyleTable().
7468
7469
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7470
7471
 @return pointer to a style table which should not be modified or freed by the
7472
 caller.
7473
*/
7474
7475
OGRStyleTable *GDALDataset::GetStyleTable()
7476
0
{
7477
0
    return m_poStyleTable;
7478
0
}
7479
7480
/************************************************************************/
7481
/*                         SetStyleTableDirectly()                      */
7482
/************************************************************************/
7483
7484
/**
7485
 \brief Set dataset style table.
7486
7487
 This method operate exactly as SetStyleTable() except that it
7488
 assumes ownership of the passed table.
7489
7490
 This method is the same as the C function GDALDatasetSetStyleTableDirectly()
7491
 and the deprecated OGR_DS_SetStyleTableDirectly().
7492
7493
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7494
7495
 @param poStyleTable pointer to style table to set
7496
7497
*/
7498
void GDALDataset::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
7499
0
{
7500
0
    if (m_poStyleTable)
7501
0
        delete m_poStyleTable;
7502
0
    m_poStyleTable = poStyleTable;
7503
0
}
7504
7505
/************************************************************************/
7506
/*                            SetStyleTable()                           */
7507
/************************************************************************/
7508
7509
/**
7510
 \brief Set dataset style table.
7511
7512
 This method operate exactly as SetStyleTableDirectly() except
7513
 that it does not assume ownership of the passed table.
7514
7515
 This method is the same as the C function GDALDatasetSetStyleTable() and the
7516
 deprecated OGR_DS_SetStyleTable().
7517
7518
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7519
7520
 @param poStyleTable pointer to style table to set
7521
7522
*/
7523
7524
void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
7525
0
{
7526
0
    if (m_poStyleTable)
7527
0
        delete m_poStyleTable;
7528
0
    if (poStyleTable)
7529
0
        m_poStyleTable = poStyleTable->Clone();
7530
0
}
7531
7532
/************************************************************************/
7533
/*                         IsGenericSQLDialect()                        */
7534
/************************************************************************/
7535
7536
//! @cond Doxygen_Suppress
7537
int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
7538
0
{
7539
0
    return pszDialect != nullptr &&
7540
0
           (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
7541
0
}
7542
7543
//! @endcond
7544
7545
/************************************************************************/
7546
/*                            GetLayerCount()                           */
7547
/************************************************************************/
7548
7549
/**
7550
 \brief Get the number of layers in this dataset.
7551
7552
 This method is the same as the C function GDALDatasetGetLayerCount(),
7553
 and the deprecated OGR_DS_GetLayerCount().
7554
7555
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7556
7557
 @return layer count.
7558
*/
7559
7560
int GDALDataset::GetLayerCount()
7561
0
{
7562
0
    return 0;
7563
0
}
7564
7565
/************************************************************************/
7566
/*                                GetLayer()                            */
7567
/************************************************************************/
7568
7569
/**
7570
 \fn GDALDataset::GetLayer(int)
7571
 \brief Fetch a layer by index.
7572
7573
 The returned layer remains owned by the
7574
 GDALDataset and should not be deleted by the application.
7575
7576
 See GetLayers() for a C++ iterator version of this method.
7577
7578
 This method is the same as the C function GDALDatasetGetLayer() and the
7579
 deprecated OGR_DS_GetLayer().
7580
7581
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7582
7583
 @param iLayer a layer number between 0 and GetLayerCount()-1.
7584
7585
 @return the layer, or NULL if iLayer is out of range or an error occurs.
7586
7587
 @see GetLayers()
7588
*/
7589
7590
OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer)
7591
0
{
7592
0
    return nullptr;
7593
0
}
7594
7595
/************************************************************************/
7596
/*                                IsLayerPrivate()                      */
7597
/************************************************************************/
7598
7599
/**
7600
 \fn GDALDataset::IsLayerPrivate(int)
7601
 \brief Returns true if the layer at the specified index is deemed a private or
7602
 system table, or an internal detail only.
7603
7604
 This method is the same as the C function GDALDatasetIsLayerPrivate().
7605
7606
 @param iLayer a layer number between 0 and GetLayerCount()-1.
7607
7608
 @return true if the layer is a private or system table.
7609
7610
 @since GDAL 3.4
7611
*/
7612
7613
bool GDALDataset::IsLayerPrivate(CPL_UNUSED int iLayer) const
7614
0
{
7615
0
    return false;
7616
0
}
7617
7618
/************************************************************************/
7619
/*                           ResetReading()                             */
7620
/************************************************************************/
7621
7622
/**
7623
 \brief Reset feature reading to start on the first feature.
7624
7625
 This affects GetNextFeature().
7626
7627
 Depending on drivers, this may also have the side effect of calling
7628
 OGRLayer::ResetReading() on the layers of this dataset.
7629
7630
 This method is the same as the C function GDALDatasetResetReading().
7631
7632
 @since GDAL 2.2
7633
*/
7634
void GDALDataset::ResetReading()
7635
0
{
7636
0
    if (!m_poPrivate)
7637
0
        return;
7638
0
    m_poPrivate->nCurrentLayerIdx = 0;
7639
0
    m_poPrivate->nLayerCount = -1;
7640
0
    m_poPrivate->poCurrentLayer = nullptr;
7641
0
    m_poPrivate->nFeatureReadInLayer = 0;
7642
0
    m_poPrivate->nFeatureReadInDataset = 0;
7643
0
    m_poPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
7644
0
    m_poPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
7645
0
}
7646
7647
/************************************************************************/
7648
/*                         GDALDatasetResetReading()                    */
7649
/************************************************************************/
7650
7651
/**
7652
 \brief Reset feature reading to start on the first feature.
7653
7654
 This affects GDALDatasetGetNextFeature().
7655
7656
 Depending on drivers, this may also have the side effect of calling
7657
 OGR_L_ResetReading() on the layers of this dataset.
7658
7659
 This method is the same as the C++ method GDALDataset::ResetReading()
7660
7661
 @param hDS dataset handle
7662
 @since GDAL 2.2
7663
*/
7664
void CPL_DLL GDALDatasetResetReading(GDALDatasetH hDS)
7665
0
{
7666
0
    VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
7667
7668
0
    return GDALDataset::FromHandle(hDS)->ResetReading();
7669
0
}
7670
7671
/************************************************************************/
7672
/*                          GetNextFeature()                            */
7673
/************************************************************************/
7674
7675
/**
7676
 \brief Fetch the next available feature from this dataset.
7677
7678
 This method is intended for the few drivers where OGRLayer::GetNextFeature()
7679
 is not efficient, but in general OGRLayer::GetNextFeature() is a more
7680
 natural API.
7681
7682
 See GetFeatures() for a C++ iterator version of this method.
7683
7684
 The returned feature becomes the responsibility of the caller to
7685
 delete with OGRFeature::DestroyFeature().
7686
7687
 Depending on the driver, this method may return features from layers in a
7688
 non sequential way. This is what may happen when the
7689
 ODsCRandomLayerRead capability is declared (for example for the
7690
 OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7691
 advised to use GDALDataset::GetNextFeature() instead of
7692
 OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7693
 implementation.
7694
7695
 The default implementation, used by most drivers, will
7696
 however iterate over each layer, and then over each feature within this
7697
 layer.
7698
7699
 This method takes into account spatial and attribute filters set on layers that
7700
 will be iterated upon.
7701
7702
 The ResetReading() method can be used to start at the beginning again.
7703
7704
 Depending on drivers, this may also have the side effect of calling
7705
 OGRLayer::GetNextFeature() on the layers of this dataset.
7706
7707
 This method is the same as the C function GDALDatasetGetNextFeature().
7708
7709
 @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
7710
                          layer to which the object belongs to, or NULL.
7711
                          It is possible that the output of *ppoBelongingLayer
7712
                          to be NULL despite the feature not being NULL.
7713
 @param pdfProgressPct    a pointer to a double variable to receive the
7714
                          percentage progress (in [0,1] range), or NULL.
7715
                          On return, the pointed value might be negative if
7716
                          determining the progress is not possible.
7717
 @param pfnProgress       a progress callback to report progress (for
7718
                          GetNextFeature() calls that might have a long
7719
                          duration) and offer cancellation possibility, or NULL.
7720
 @param pProgressData     user data provided to pfnProgress, or NULL
7721
 @return a feature, or NULL if no more features are available.
7722
 @since GDAL 2.2
7723
 @see GetFeatures()
7724
*/
7725
7726
OGRFeature *GDALDataset::GetNextFeature(OGRLayer **ppoBelongingLayer,
7727
                                        double *pdfProgressPct,
7728
                                        GDALProgressFunc pfnProgress,
7729
                                        void *pProgressData)
7730
0
{
7731
0
    if (!m_poPrivate || m_poPrivate->nCurrentLayerIdx < 0)
7732
0
    {
7733
0
        if (ppoBelongingLayer != nullptr)
7734
0
            *ppoBelongingLayer = nullptr;
7735
0
        if (pdfProgressPct != nullptr)
7736
0
            *pdfProgressPct = 1.0;
7737
0
        if (pfnProgress != nullptr)
7738
0
            pfnProgress(1.0, "", pProgressData);
7739
0
        return nullptr;
7740
0
    }
7741
7742
0
    if (m_poPrivate->poCurrentLayer == nullptr &&
7743
0
        (pdfProgressPct != nullptr || pfnProgress != nullptr))
7744
0
    {
7745
0
        if (m_poPrivate->nLayerCount < 0)
7746
0
        {
7747
0
            m_poPrivate->nLayerCount = GetLayerCount();
7748
0
        }
7749
7750
0
        if (m_poPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT)
7751
0
        {
7752
0
            m_poPrivate->nTotalFeatures = 0;
7753
0
            for (int i = 0; i < m_poPrivate->nLayerCount; i++)
7754
0
            {
7755
0
                OGRLayer *poLayer = GetLayer(i);
7756
0
                if (poLayer == nullptr ||
7757
0
                    !poLayer->TestCapability(OLCFastFeatureCount))
7758
0
                {
7759
0
                    m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7760
0
                    break;
7761
0
                }
7762
0
                GIntBig nCount = poLayer->GetFeatureCount(FALSE);
7763
0
                if (nCount < 0)
7764
0
                {
7765
0
                    m_poPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
7766
0
                    break;
7767
0
                }
7768
0
                m_poPrivate->nTotalFeatures += nCount;
7769
0
            }
7770
0
        }
7771
0
    }
7772
7773
0
    while (true)
7774
0
    {
7775
0
        if (m_poPrivate->poCurrentLayer == nullptr)
7776
0
        {
7777
0
            m_poPrivate->poCurrentLayer =
7778
0
                GetLayer(m_poPrivate->nCurrentLayerIdx);
7779
0
            if (m_poPrivate->poCurrentLayer == nullptr)
7780
0
            {
7781
0
                m_poPrivate->nCurrentLayerIdx = -1;
7782
0
                if (ppoBelongingLayer != nullptr)
7783
0
                    *ppoBelongingLayer = nullptr;
7784
0
                if (pdfProgressPct != nullptr)
7785
0
                    *pdfProgressPct = 1.0;
7786
0
                return nullptr;
7787
0
            }
7788
0
            m_poPrivate->poCurrentLayer->ResetReading();
7789
0
            m_poPrivate->nFeatureReadInLayer = 0;
7790
0
            if (m_poPrivate->nTotalFeatures < 0 && pdfProgressPct != nullptr)
7791
0
            {
7792
0
                if (m_poPrivate->poCurrentLayer->TestCapability(
7793
0
                        OLCFastFeatureCount))
7794
0
                    m_poPrivate->nTotalFeaturesInLayer =
7795
0
                        m_poPrivate->poCurrentLayer->GetFeatureCount(FALSE);
7796
0
                else
7797
0
                    m_poPrivate->nTotalFeaturesInLayer = 0;
7798
0
            }
7799
0
        }
7800
0
        OGRFeature *poFeature = m_poPrivate->poCurrentLayer->GetNextFeature();
7801
0
        if (poFeature == nullptr)
7802
0
        {
7803
0
            m_poPrivate->nCurrentLayerIdx++;
7804
0
            m_poPrivate->poCurrentLayer = nullptr;
7805
0
            continue;
7806
0
        }
7807
7808
0
        m_poPrivate->nFeatureReadInLayer++;
7809
0
        m_poPrivate->nFeatureReadInDataset++;
7810
0
        if (pdfProgressPct != nullptr || pfnProgress != nullptr)
7811
0
        {
7812
0
            double dfPct = 0.0;
7813
0
            if (m_poPrivate->nTotalFeatures > 0)
7814
0
            {
7815
0
                dfPct = 1.0 * m_poPrivate->nFeatureReadInDataset /
7816
0
                        m_poPrivate->nTotalFeatures;
7817
0
            }
7818
0
            else
7819
0
            {
7820
0
                dfPct = 1.0 * m_poPrivate->nCurrentLayerIdx /
7821
0
                        m_poPrivate->nLayerCount;
7822
0
                if (m_poPrivate->nTotalFeaturesInLayer > 0)
7823
0
                {
7824
0
                    dfPct += 1.0 * m_poPrivate->nFeatureReadInLayer /
7825
0
                             m_poPrivate->nTotalFeaturesInLayer /
7826
0
                             m_poPrivate->nLayerCount;
7827
0
                }
7828
0
            }
7829
0
            if (pdfProgressPct)
7830
0
                *pdfProgressPct = dfPct;
7831
0
            if (pfnProgress)
7832
0
                pfnProgress(dfPct, "", nullptr);
7833
0
        }
7834
7835
0
        if (ppoBelongingLayer != nullptr)
7836
0
            *ppoBelongingLayer = m_poPrivate->poCurrentLayer;
7837
0
        return poFeature;
7838
0
    }
7839
0
}
7840
7841
/************************************************************************/
7842
/*                     GDALDatasetGetNextFeature()                      */
7843
/************************************************************************/
7844
/**
7845
 \brief Fetch the next available feature from this dataset.
7846
7847
 This method is intended for the few drivers where OGR_L_GetNextFeature()
7848
 is not efficient, but in general OGR_L_GetNextFeature() is a more
7849
 natural API.
7850
7851
 The returned feature becomes the responsibility of the caller to
7852
 delete with OGRFeature::DestroyFeature().
7853
7854
 Depending on the driver, this method may return features from layers in a
7855
 non sequential way. This is what may happen when the
7856
 ODsCRandomLayerRead capability is declared (for example for the
7857
 OSM and GMLAS drivers). When datasets declare this capability, it is strongly
7858
 advised to use GDALDataset::GetNextFeature() instead of
7859
 OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
7860
 implementation.
7861
7862
 The default implementation, used by most drivers, will
7863
 however iterate over each layer, and then over each feature within this
7864
 layer.
7865
7866
 This method takes into account spatial and attribute filters set on layers that
7867
 will be iterated upon.
7868
7869
 The ResetReading() method can be used to start at the beginning again.
7870
7871
 Depending on drivers, this may also have the side effect of calling
7872
 OGRLayer::GetNextFeature() on the layers of this dataset.
7873
7874
 This method is the same as the C++ method GDALDataset::GetNextFeature()
7875
7876
 @param hDS               dataset handle.
7877
 @param phBelongingLayer  a pointer to a OGRLayer* variable to receive the
7878
                          layer to which the object belongs to, or NULL.
7879
                          It is possible that the output of *ppoBelongingLayer
7880
                          to be NULL despite the feature not being NULL.
7881
 @param pdfProgressPct    a pointer to a double variable to receive the
7882
                          percentage progress (in [0,1] range), or NULL.
7883
                          On return, the pointed value might be negative if
7884
                          determining the progress is not possible.
7885
 @param pfnProgress       a progress callback to report progress (for
7886
                          GetNextFeature() calls that might have a long
7887
                          duration) and offer cancellation possibility, or NULL
7888
 @param pProgressData     user data provided to pfnProgress, or NULL
7889
 @return a feature, or NULL if no more features are available.
7890
 @since GDAL 2.2
7891
*/
7892
OGRFeatureH CPL_DLL GDALDatasetGetNextFeature(GDALDatasetH hDS,
7893
                                              OGRLayerH *phBelongingLayer,
7894
                                              double *pdfProgressPct,
7895
                                              GDALProgressFunc pfnProgress,
7896
                                              void *pProgressData)
7897
0
{
7898
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", nullptr);
7899
7900
0
    return OGRFeature::ToHandle(GDALDataset::FromHandle(hDS)->GetNextFeature(
7901
0
        reinterpret_cast<OGRLayer **>(phBelongingLayer), pdfProgressPct,
7902
0
        pfnProgress, pProgressData));
7903
0
}
7904
7905
/************************************************************************/
7906
/*                            TestCapability()                          */
7907
/************************************************************************/
7908
7909
/**
7910
 \fn GDALDataset::TestCapability( const char * pszCap )
7911
 \brief Test if capability is available.
7912
7913
 One of the following dataset capability names can be passed into this
7914
 method, and a TRUE or FALSE value will be returned indicating whether or not
7915
 the capability is available for this object.
7916
7917
 <ul>
7918
  <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7919
  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7920
          layers.<p>
7921
  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7922
          datasource support CreateGeomField() just after layer creation.<p>
7923
  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7924
          geometries.<p>
7925
  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7926
          transactions.<p>
7927
  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7928
          transactions through emulation.<p>
7929
  <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7930
          GetNextFeature() implementation, potentially returning features from
7931
          layers in a non sequential way.<p>
7932
  <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7933
         CreateFeature() on layers in a non sequential way.<p>
7934
  <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
7935
  <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
7936
  <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
7937
  <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
7938
  <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
7939
 </ul>
7940
7941
 The \#define macro forms of the capability names should be used in preference
7942
 to the strings themselves to avoid misspelling.
7943
7944
 This method is the same as the C function GDALDatasetTestCapability() and the
7945
 deprecated OGR_DS_TestCapability().
7946
7947
 In GDAL 1.X, this method used to be in the OGRDataSource class.
7948
7949
 @param pszCap the capability to test.
7950
7951
 @return TRUE if capability available otherwise FALSE.
7952
*/
7953
7954
int GDALDataset::TestCapability(const char *pszCap)
7955
0
{
7956
0
    if (EQUAL(pszCap, GDsCFastGetExtent) ||
7957
0
        EQUAL(pszCap, GDsCFastGetExtentWGS84LongLat))
7958
0
    {
7959
0
        for (auto &&poLayer : GetLayers())
7960
0
        {
7961
0
            if (!poLayer->TestCapability(OLCFastGetExtent))
7962
0
                return FALSE;
7963
0
        }
7964
0
        return TRUE;
7965
0
    }
7966
0
    return FALSE;
7967
0
}
7968
7969
/************************************************************************/
7970
/*                     GDALDatasetTestCapability()                      */
7971
/************************************************************************/
7972
7973
/**
7974
 \brief Test if capability is available.
7975
7976
 One of the following dataset capability names can be passed into this
7977
 function, and a TRUE or FALSE value will be returned indicating whether or not
7978
 the capability is available for this object.
7979
7980
 <ul>
7981
  <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
7982
  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
7983
          layers.<p>
7984
  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
7985
          datasource support CreateGeomField() just after layer creation.<p>
7986
  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
7987
          geometries.<p>
7988
  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
7989
          transactions.<p>
7990
  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
7991
          transactions through emulation.<p>
7992
  <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
7993
          GetNextFeature() implementation, potentially returning features from
7994
          layers in a non sequential way.<p>
7995
  <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
7996
          CreateFeature() on layers in a non sequential way.<p>
7997
  <li> <b>GDsCAddRelationship</b>: True if AddRelationship() is supported</li>
7998
  <li> <b>GDsCDeleteRelationship</b>: True if DeleteRelationship() is supported</li>
7999
  <li> <b>GDsCUpdateRelationship</b>: True if UpdateRelationship() is supported</li>
8000
  <li> <b>GDsCFastGetExtent</b>: True if GetExtent() is fast</li>
8001
  <li> <b>GDsCFastGetExtentWGS84LongLat</b>: True if GetExtentWGS84LongLat() is fast</li>
8002
 </ul>
8003
8004
 The \#define macro forms of the capability names should be used in preference
8005
 to the strings themselves to avoid misspelling.
8006
8007
 This function is the same as the C++ method GDALDataset::TestCapability()
8008
8009
 @since GDAL 2.0
8010
8011
 @param hDS the dataset handle.
8012
 @param pszCap the capability to test.
8013
8014
 @return TRUE if capability available otherwise FALSE.
8015
*/
8016
int GDALDatasetTestCapability(GDALDatasetH hDS, const char *pszCap)
8017
8018
0
{
8019
0
    VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
8020
0
    VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
8021
8022
0
    return GDALDataset::FromHandle(hDS)->TestCapability(pszCap);
8023
0
}
8024
8025
/************************************************************************/
8026
/*                           StartTransaction()                         */
8027
/************************************************************************/
8028
8029
/**
8030
 \fn GDALDataset::StartTransaction(int)
8031
 \brief For datasources which support transactions, StartTransaction creates a
8032
`transaction.
8033
8034
 If starting the transaction fails, will return
8035
 OGRERR_FAILURE. Datasources which do not support transactions will
8036
 always return OGRERR_UNSUPPORTED_OPERATION.
8037
8038
 Nested transactions are not supported.
8039
8040
 All changes done after the start of the transaction are definitely applied in
8041
 the datasource if CommitTransaction() is called. They may be canceled by
8042
 calling RollbackTransaction() instead.
8043
8044
 At the time of writing, transactions only apply on vector layers.
8045
8046
 Datasets that support transactions will advertise the ODsCTransactions
8047
 capability.  Use of transactions at dataset level is generally preferred to
8048
 transactions at layer level, whose scope is rarely limited to the layer from
8049
 which it was started.
8050
8051
 In case StartTransaction() fails, neither CommitTransaction() or
8052
 RollbackTransaction() should be called.
8053
8054
 If an error occurs after a successful StartTransaction(), the whole transaction
8055
 may or may not be implicitly canceled, depending on drivers. (e.g.  the PG
8056
 driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
8057
 an explicit call to RollbackTransaction() should be done to keep things
8058
 balanced.
8059
8060
 By default, when bForce is set to FALSE, only "efficient" transactions will be
8061
 attempted. Some drivers may offer an emulation of transactions, but sometimes
8062
 with significant overhead, in which case the user must explicitly allow for
8063
 such an emulation by setting bForce to TRUE. Drivers that offer emulated
8064
 transactions should advertise the ODsCEmulatedTransactions capability (and not
8065
 ODsCTransactions).
8066
8067
 This function is the same as the C function GDALDatasetStartTransaction().
8068
8069
 @param bForce can be set to TRUE if an emulation, possibly slow, of a
8070
 transaction
8071
               mechanism is acceptable.
8072
8073
 @return OGRERR_NONE on success.
8074
 @since GDAL 2.0
8075
*/
8076
8077
OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
8078
0
{
8079
0
    return OGRERR_UNSUPPORTED_OPERATION;
8080
0
}
8081
8082
/************************************************************************/
8083
/*                      GDALDatasetStartTransaction()                   */
8084
/************************************************************************/
8085
8086
/**
8087
 \brief For datasources which support transactions, StartTransaction creates a
8088
 transaction.
8089
8090
 If starting the transaction fails, will return
8091
 OGRERR_FAILURE. Datasources which do not support transactions will
8092
 always return OGRERR_UNSUPPORTED_OPERATION.
8093
8094
 Nested transactions are not supported.
8095
8096
 All changes done after the start of the transaction are definitely applied in
8097
 the datasource if CommitTransaction() is called. They may be canceled by
8098
 calling RollbackTransaction() instead.
8099
8100
 At the time of writing, transactions only apply on vector layers.
8101
8102
 Datasets that support transactions will advertise the ODsCTransactions
8103
 capability.
8104
 Use of transactions at dataset level is generally preferred to transactions at
8105
 layer level, whose scope is rarely limited to the layer from which it was
8106
 started.
8107
8108
 In case StartTransaction() fails, neither CommitTransaction() or
8109
 RollbackTransaction() should be called.
8110
8111
 If an error occurs after a successful StartTransaction(), the whole
8112
 transaction may or may not be implicitly canceled, depending on drivers. (e.g.
8113
 the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
8114
 error, an explicit call to RollbackTransaction() should be done to keep things
8115
 balanced.
8116
8117
 By default, when bForce is set to FALSE, only "efficient" transactions will be
8118
 attempted. Some drivers may offer an emulation of transactions, but sometimes
8119
 with significant overhead, in which case the user must explicitly allow for
8120
 such an emulation by setting bForce to TRUE. Drivers that offer emulated
8121
 transactions should advertise the ODsCEmulatedTransactions capability (and not
8122
 ODsCTransactions).
8123
8124
 This function is the same as the C++ method GDALDataset::StartTransaction()
8125
8126
 @param hDS the dataset handle.
8127
 @param bForce can be set to TRUE if an emulation, possibly slow, of a
8128
 transaction
8129
               mechanism is acceptable.
8130
8131
 @return OGRERR_NONE on success.
8132
 @since GDAL 2.0
8133
*/
8134
OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
8135
0
{
8136
0
    VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
8137
0
                      OGRERR_INVALID_HANDLE);
8138
8139
0
#ifdef OGRAPISPY_ENABLED
8140
0
    if (bOGRAPISpyEnabled)
8141
0
        OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
8142
0
#endif
8143
8144
0
    return GDALDataset::FromHandle(hDS)->StartTransaction(bForce);
8145
0
}
8146
8147
/************************************************************************/
8148
/*                           CommitTransaction()                        */
8149
/************************************************************************/
8150
8151
/**
8152
 \brief For datasources which support transactions, CommitTransaction commits a
8153
 transaction.
8154
8155
 If no transaction is active, or the commit fails, will return
8156
 OGRERR_FAILURE. Datasources which do not support transactions will
8157
 always return OGRERR_UNSUPPORTED_OPERATION.
8158
8159
 Depending on drivers, this may or may not abort layer sequential readings that
8160
 are active.
8161
8162
 This function is the same as the C function GDALDatasetCommitTransaction().
8163
8164
 @return OGRERR_NONE on success.
8165
 @since GDAL 2.0
8166
*/
8167
OGRErr GDALDataset::CommitTransaction()
8168
0
{
8169
0
    return OGRERR_UNSUPPORTED_OPERATION;
8170
0
}
8171
8172
/************************************************************************/
8173
/*                        GDALDatasetCommitTransaction()                */
8174
/************************************************************************/
8175
8176
/**
8177
 \brief For datasources which support transactions, CommitTransaction commits a
8178
 transaction.
8179
8180
 If no transaction is active, or the commit fails, will return
8181
 OGRERR_FAILURE. Datasources which do not support transactions will
8182
 always return OGRERR_UNSUPPORTED_OPERATION.
8183
8184
 Depending on drivers, this may or may not abort layer sequential readings that
8185
 are active.
8186
8187
 This function is the same as the C++ method GDALDataset::CommitTransaction()
8188
8189
 @return OGRERR_NONE on success.
8190
 @since GDAL 2.0
8191
*/
8192
OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
8193
0
{
8194
0
    VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
8195
0
                      OGRERR_INVALID_HANDLE);
8196
8197
0
#ifdef OGRAPISPY_ENABLED
8198
0
    if (bOGRAPISpyEnabled)
8199
0
        OGRAPISpy_Dataset_CommitTransaction(hDS);
8200
0
#endif
8201
8202
0
    return GDALDataset::FromHandle(hDS)->CommitTransaction();
8203
0
}
8204
8205
/************************************************************************/
8206
/*                           RollbackTransaction()                      */
8207
/************************************************************************/
8208
8209
/**
8210
 \brief For datasources which support transactions, RollbackTransaction will
8211
 roll back a datasource to its state before the start of the current
8212
 transaction.
8213
 If no transaction is active, or the rollback fails, will return
8214
 OGRERR_FAILURE. Datasources which do not support transactions will
8215
 always return OGRERR_UNSUPPORTED_OPERATION.
8216
8217
 This function is the same as the C function GDALDatasetRollbackTransaction().
8218
8219
 @return OGRERR_NONE on success.
8220
 @since GDAL 2.0
8221
*/
8222
OGRErr GDALDataset::RollbackTransaction()
8223
0
{
8224
0
    return OGRERR_UNSUPPORTED_OPERATION;
8225
0
}
8226
8227
/************************************************************************/
8228
/*                     GDALDatasetRollbackTransaction()                 */
8229
/************************************************************************/
8230
8231
/**
8232
 \brief For datasources which support transactions, RollbackTransaction will
8233
 roll back a datasource to its state before the start of the current
8234
 transaction.
8235
 If no transaction is active, or the rollback fails, will return
8236
 OGRERR_FAILURE. Datasources which do not support transactions will
8237
 always return OGRERR_UNSUPPORTED_OPERATION.
8238
8239
 This function is the same as the C++ method GDALDataset::RollbackTransaction().
8240
8241
 @return OGRERR_NONE on success.
8242
 @since GDAL 2.0
8243
*/
8244
OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
8245
0
{
8246
0
    VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
8247
0
                      OGRERR_INVALID_HANDLE);
8248
8249
0
#ifdef OGRAPISPY_ENABLED
8250
0
    if (bOGRAPISpyEnabled)
8251
0
        OGRAPISpy_Dataset_RollbackTransaction(hDS);
8252
0
#endif
8253
8254
0
    return GDALDataset::FromHandle(hDS)->RollbackTransaction();
8255
0
}
8256
8257
//! @cond Doxygen_Suppress
8258
8259
/************************************************************************/
8260
/*                   ShareLockWithParentDataset()                       */
8261
/************************************************************************/
8262
8263
/* To be used typically by the GTiff driver to link overview datasets */
8264
/* with their main dataset, so that they share the same lock */
8265
/* Cf https://github.com/OSGeo/gdal/issues/1488 */
8266
/* The parent dataset should remain alive while the this dataset is alive */
8267
8268
void GDALDataset::ShareLockWithParentDataset(GDALDataset *poParentDataset)
8269
0
{
8270
0
    if (m_poPrivate != nullptr)
8271
0
    {
8272
0
        m_poPrivate->poParentDataset = poParentDataset;
8273
0
    }
8274
0
}
8275
8276
/************************************************************************/
8277
/*                   SetQueryLoggerFunc()                               */
8278
/************************************************************************/
8279
8280
bool GDALDataset::SetQueryLoggerFunc(CPL_UNUSED GDALQueryLoggerFunc callback,
8281
                                     CPL_UNUSED void *context)
8282
0
{
8283
0
    return false;
8284
0
}
8285
8286
/************************************************************************/
8287
/*                          EnterReadWrite()                            */
8288
/************************************************************************/
8289
8290
int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
8291
0
{
8292
0
    if (m_poPrivate == nullptr ||
8293
0
        IsThreadSafe(GDAL_OF_RASTER | (nOpenFlags & GDAL_OF_UPDATE)))
8294
0
        return FALSE;
8295
8296
0
    if (m_poPrivate->poParentDataset)
8297
0
        return m_poPrivate->poParentDataset->EnterReadWrite(eRWFlag);
8298
8299
0
    if (eAccess == GA_Update)
8300
0
    {
8301
0
        if (m_poPrivate->eStateReadWriteMutex ==
8302
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8303
0
        {
8304
            // In case dead-lock would occur, which is not impossible,
8305
            // this can be used to prevent it, but at the risk of other
8306
            // issues.
8307
0
            if (CPLTestBool(
8308
0
                    CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
8309
0
            {
8310
0
                m_poPrivate->eStateReadWriteMutex =
8311
0
                    GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED;
8312
0
            }
8313
0
            else
8314
0
            {
8315
0
                m_poPrivate->eStateReadWriteMutex =
8316
0
                    GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8317
0
            }
8318
0
        }
8319
0
        if (m_poPrivate->eStateReadWriteMutex ==
8320
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_ALLOWED)
8321
0
        {
8322
            // There should be no race related to creating this mutex since
8323
            // it should be first created through IWriteBlock() / IRasterIO()
8324
            // and then GDALRasterBlock might call it from another thread.
8325
#ifdef DEBUG_VERBOSE
8326
            CPLDebug("GDAL",
8327
                     "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
8328
                     CPLGetPID(), GetDescription());
8329
#endif
8330
0
            CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8331
8332
0
            const int nCountMutex =
8333
0
                m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
8334
0
            if (nCountMutex == 0 && eRWFlag == GF_Read)
8335
0
            {
8336
0
                CPLReleaseMutex(m_poPrivate->hMutex);
8337
0
                for (int i = 0; i < nBands; i++)
8338
0
                {
8339
0
                    auto blockCache = papoBands[i]->poBandBlockCache;
8340
0
                    if (blockCache)
8341
0
                        blockCache->WaitCompletionPendingTasks();
8342
0
                }
8343
0
                CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8344
0
            }
8345
8346
0
            return TRUE;
8347
0
        }
8348
0
    }
8349
0
    return FALSE;
8350
0
}
8351
8352
/************************************************************************/
8353
/*                         LeaveReadWrite()                             */
8354
/************************************************************************/
8355
8356
void GDALDataset::LeaveReadWrite()
8357
0
{
8358
0
    if (m_poPrivate)
8359
0
    {
8360
0
        if (m_poPrivate->poParentDataset)
8361
0
        {
8362
0
            m_poPrivate->poParentDataset->LeaveReadWrite();
8363
0
            return;
8364
0
        }
8365
8366
0
        m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
8367
0
        CPLReleaseMutex(m_poPrivate->hMutex);
8368
#ifdef DEBUG_VERBOSE
8369
        CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
8370
                 CPLGetPID(), GetDescription());
8371
#endif
8372
0
    }
8373
0
}
8374
8375
/************************************************************************/
8376
/*                           InitRWLock()                               */
8377
/************************************************************************/
8378
8379
void GDALDataset::InitRWLock()
8380
0
{
8381
0
    if (m_poPrivate)
8382
0
    {
8383
0
        if (m_poPrivate->poParentDataset)
8384
0
        {
8385
0
            m_poPrivate->poParentDataset->InitRWLock();
8386
0
            return;
8387
0
        }
8388
8389
0
        if (m_poPrivate->eStateReadWriteMutex ==
8390
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_UNKNOWN)
8391
0
        {
8392
0
            if (EnterReadWrite(GF_Write))
8393
0
                LeaveReadWrite();
8394
0
        }
8395
0
    }
8396
0
}
8397
8398
/************************************************************************/
8399
/*                       DisableReadWriteMutex()                        */
8400
/************************************************************************/
8401
8402
// The mutex logic is broken in multi-threaded situations, for example
8403
// with 2 WarpedVRT datasets being read at the same time. In that
8404
// particular case, the mutex is not needed, so allow the VRTWarpedDataset code
8405
// to disable it.
8406
void GDALDataset::DisableReadWriteMutex()
8407
0
{
8408
0
    if (m_poPrivate)
8409
0
    {
8410
0
        if (m_poPrivate->poParentDataset)
8411
0
        {
8412
0
            m_poPrivate->poParentDataset->DisableReadWriteMutex();
8413
0
            return;
8414
0
        }
8415
8416
0
        m_poPrivate->eStateReadWriteMutex =
8417
0
            GDALAllowReadWriteMutexState::RW_MUTEX_STATE_DISABLED;
8418
0
    }
8419
0
}
8420
8421
/************************************************************************/
8422
/*                      TemporarilyDropReadWriteLock()                  */
8423
/************************************************************************/
8424
8425
void GDALDataset::TemporarilyDropReadWriteLock()
8426
0
{
8427
0
    if (m_poPrivate == nullptr)
8428
0
        return;
8429
8430
0
    if (m_poPrivate->poParentDataset)
8431
0
    {
8432
0
        m_poPrivate->poParentDataset->TemporarilyDropReadWriteLock();
8433
0
        return;
8434
0
    }
8435
8436
0
#ifndef __COVERITY__
8437
0
    if (m_poPrivate->hMutex)
8438
0
    {
8439
#ifdef DEBUG_VERBOSE
8440
        CPLDebug("GDAL",
8441
                 "[Thread " CPL_FRMT_GIB "] "
8442
                 "Temporarily drop RW mutex for %s",
8443
                 CPLGetPID(), GetDescription());
8444
#endif
8445
0
        CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8446
0
        const int nCount =
8447
0
            m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8448
#ifdef DEBUG_EXTRA
8449
        m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
8450
#endif
8451
0
        for (int i = 0; i < nCount + 1; i++)
8452
0
        {
8453
            // The mutex is recursive
8454
0
            CPLReleaseMutex(m_poPrivate->hMutex);
8455
0
        }
8456
0
    }
8457
0
#endif
8458
0
}
8459
8460
/************************************************************************/
8461
/*                       ReacquireReadWriteLock()                       */
8462
/************************************************************************/
8463
8464
void GDALDataset::ReacquireReadWriteLock()
8465
0
{
8466
0
    if (m_poPrivate == nullptr)
8467
0
        return;
8468
8469
0
    if (m_poPrivate->poParentDataset)
8470
0
    {
8471
0
        m_poPrivate->poParentDataset->ReacquireReadWriteLock();
8472
0
        return;
8473
0
    }
8474
8475
0
#ifndef __COVERITY__
8476
0
    if (m_poPrivate->hMutex)
8477
0
    {
8478
#ifdef DEBUG_VERBOSE
8479
        CPLDebug("GDAL",
8480
                 "[Thread " CPL_FRMT_GIB "] "
8481
                 "Reacquire temporarily dropped RW mutex for %s",
8482
                 CPLGetPID(), GetDescription());
8483
#endif
8484
0
        CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8485
0
        const int nCount =
8486
0
            m_poPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
8487
#ifdef DEBUG_EXTRA
8488
        CPLAssert(nCount ==
8489
                  m_poPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
8490
#endif
8491
0
        if (nCount == 0)
8492
0
            CPLReleaseMutex(m_poPrivate->hMutex);
8493
0
        for (int i = 0; i < nCount - 1; i++)
8494
0
        {
8495
            // The mutex is recursive
8496
0
            CPLAcquireMutex(m_poPrivate->hMutex, 1000.0);
8497
0
        }
8498
0
    }
8499
0
#endif
8500
0
}
8501
8502
/************************************************************************/
8503
/*                           AcquireMutex()                             */
8504
/************************************************************************/
8505
8506
int GDALDataset::AcquireMutex()
8507
0
{
8508
0
    if (m_poPrivate == nullptr)
8509
0
        return 0;
8510
0
    if (m_poPrivate->poParentDataset)
8511
0
    {
8512
0
        return m_poPrivate->poParentDataset->AcquireMutex();
8513
0
    }
8514
8515
0
    return CPLCreateOrAcquireMutex(&(m_poPrivate->hMutex), 1000.0);
8516
0
}
8517
8518
/************************************************************************/
8519
/*                          ReleaseMutex()                              */
8520
/************************************************************************/
8521
8522
void GDALDataset::ReleaseMutex()
8523
0
{
8524
0
    if (m_poPrivate)
8525
0
    {
8526
0
        if (m_poPrivate->poParentDataset)
8527
0
        {
8528
0
            m_poPrivate->poParentDataset->ReleaseMutex();
8529
0
            return;
8530
0
        }
8531
8532
0
        CPLReleaseMutex(m_poPrivate->hMutex);
8533
0
    }
8534
0
}
8535
8536
//! @endcond
8537
8538
/************************************************************************/
8539
/*              GDALDataset::Features::Iterator::Private                */
8540
/************************************************************************/
8541
8542
struct GDALDataset::Features::Iterator::Private
8543
{
8544
    GDALDataset::FeatureLayerPair m_oPair{};
8545
    GDALDataset *m_poDS = nullptr;
8546
    bool m_bEOF = true;
8547
};
8548
8549
GDALDataset::Features::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8550
0
    : m_poPrivate(new GDALDataset::Features::Iterator::Private())
8551
0
{
8552
0
    m_poPrivate->m_poDS = poDS;
8553
0
    if (bStart)
8554
0
    {
8555
0
        poDS->ResetReading();
8556
0
        m_poPrivate->m_oPair.feature.reset(poDS->GetNextFeature(
8557
0
            &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8558
0
        m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8559
0
    }
8560
0
}
8561
8562
0
GDALDataset::Features::Iterator::~Iterator() = default;
8563
8564
const GDALDataset::FeatureLayerPair &
8565
GDALDataset::Features::Iterator::operator*() const
8566
0
{
8567
0
    return m_poPrivate->m_oPair;
8568
0
}
8569
8570
GDALDataset::Features::Iterator &GDALDataset::Features::Iterator::operator++()
8571
0
{
8572
0
    m_poPrivate->m_oPair.feature.reset(m_poPrivate->m_poDS->GetNextFeature(
8573
0
        &m_poPrivate->m_oPair.layer, nullptr, nullptr, nullptr));
8574
0
    m_poPrivate->m_bEOF = m_poPrivate->m_oPair.feature == nullptr;
8575
0
    return *this;
8576
0
}
8577
8578
bool GDALDataset::Features::Iterator::operator!=(const Iterator &it) const
8579
0
{
8580
0
    return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8581
0
}
8582
8583
/************************************************************************/
8584
/*                            GetFeatures()                             */
8585
/************************************************************************/
8586
8587
/** Function that return an iterable object over features in the dataset
8588
 * layer.
8589
 *
8590
 * This is a C++ iterator friendly version of GetNextFeature().
8591
 *
8592
 * Using this iterator for standard range-based loops is safe, but
8593
 * due to implementation limitations, you shouldn't try to access
8594
 * (dereference) more than one iterator step at a time, since the
8595
 * FeatureLayerPair reference which is returned is reused.
8596
 *
8597
 * Typical use is:
8598
 * \code{.cpp}
8599
 * for( auto&& oFeatureLayerPair: poDS->GetFeatures() )
8600
 * {
8601
 *       std::cout << "Feature of layer " <<
8602
 *               oFeatureLayerPair.layer->GetName() << std::endl;
8603
 *       oFeatureLayerPair.feature->DumpReadable();
8604
 * }
8605
 * \endcode
8606
 *
8607
 * @see GetNextFeature()
8608
 *
8609
 * @since GDAL 2.3
8610
 */
8611
GDALDataset::Features GDALDataset::GetFeatures()
8612
0
{
8613
0
    return Features(this);
8614
0
}
8615
8616
/************************************************************************/
8617
/*                                 begin()                              */
8618
/************************************************************************/
8619
8620
/**
8621
 \brief Return beginning of feature iterator.
8622
8623
 @since GDAL 2.3
8624
*/
8625
8626
const GDALDataset::Features::Iterator GDALDataset::Features::begin() const
8627
0
{
8628
0
    return {m_poSelf, true};
8629
0
}
8630
8631
/************************************************************************/
8632
/*                                  end()                               */
8633
/************************************************************************/
8634
8635
/**
8636
 \brief Return end of feature iterator.
8637
8638
 @since GDAL 2.3
8639
*/
8640
8641
const GDALDataset::Features::Iterator GDALDataset::Features::end() const
8642
0
{
8643
0
    return {m_poSelf, false};
8644
0
}
8645
8646
/************************************************************************/
8647
/*               GDALDataset::Layers::Iterator::Private                 */
8648
/************************************************************************/
8649
8650
struct GDALDataset::Layers::Iterator::Private
8651
{
8652
    OGRLayer *m_poLayer = nullptr;
8653
    int m_iCurLayer = 0;
8654
    int m_nLayerCount = 0;
8655
    GDALDataset *m_poDS = nullptr;
8656
};
8657
8658
0
GDALDataset::Layers::Iterator::Iterator() : m_poPrivate(new Private())
8659
0
{
8660
0
}
8661
8662
// False positive of cppcheck 1.72
8663
// cppcheck-suppress uninitMemberVar
8664
GDALDataset::Layers::Iterator::Iterator(const Iterator &oOther)
8665
0
    : m_poPrivate(new Private(*(oOther.m_poPrivate)))
8666
0
{
8667
0
}
8668
8669
GDALDataset::Layers::Iterator::Iterator(Iterator &&oOther) noexcept
8670
0
    : m_poPrivate(std::move(oOther.m_poPrivate))
8671
0
{
8672
0
}
8673
8674
GDALDataset::Layers::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8675
0
    : m_poPrivate(new Private())
8676
0
{
8677
0
    m_poPrivate->m_poDS = poDS;
8678
0
    m_poPrivate->m_nLayerCount = poDS->GetLayerCount();
8679
0
    if (bStart)
8680
0
    {
8681
0
        if (m_poPrivate->m_nLayerCount)
8682
0
            m_poPrivate->m_poLayer = poDS->GetLayer(0);
8683
0
    }
8684
0
    else
8685
0
    {
8686
0
        m_poPrivate->m_iCurLayer = m_poPrivate->m_nLayerCount;
8687
0
    }
8688
0
}
8689
8690
0
GDALDataset::Layers::Iterator::~Iterator() = default;
8691
8692
// False positive of cppcheck 1.72
8693
// cppcheck-suppress operatorEqVarError
8694
GDALDataset::Layers::Iterator &
8695
GDALDataset::Layers::Iterator::operator=(const Iterator &oOther)
8696
0
{
8697
0
    *m_poPrivate = *oOther.m_poPrivate;
8698
0
    return *this;
8699
0
}
8700
8701
GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator=(
8702
    GDALDataset::Layers::Iterator &&oOther) noexcept
8703
0
{
8704
0
    m_poPrivate = std::move(oOther.m_poPrivate);
8705
0
    return *this;
8706
0
}
8707
8708
OGRLayer *GDALDataset::Layers::Iterator::operator*() const
8709
0
{
8710
0
    return m_poPrivate->m_poLayer;
8711
0
}
8712
8713
GDALDataset::Layers::Iterator &GDALDataset::Layers::Iterator::operator++()
8714
0
{
8715
0
    m_poPrivate->m_iCurLayer++;
8716
0
    if (m_poPrivate->m_iCurLayer < m_poPrivate->m_nLayerCount)
8717
0
    {
8718
0
        m_poPrivate->m_poLayer =
8719
0
            m_poPrivate->m_poDS->GetLayer(m_poPrivate->m_iCurLayer);
8720
0
    }
8721
0
    else
8722
0
    {
8723
0
        m_poPrivate->m_poLayer = nullptr;
8724
0
    }
8725
0
    return *this;
8726
0
}
8727
8728
GDALDataset::Layers::Iterator GDALDataset::Layers::Iterator::operator++(int)
8729
0
{
8730
0
    GDALDataset::Layers::Iterator temp = *this;
8731
0
    ++(*this);
8732
0
    return temp;
8733
0
}
8734
8735
bool GDALDataset::Layers::Iterator::operator!=(const Iterator &it) const
8736
0
{
8737
0
    return m_poPrivate->m_iCurLayer != it.m_poPrivate->m_iCurLayer;
8738
0
}
8739
8740
/************************************************************************/
8741
/*                             GetLayers()                              */
8742
/************************************************************************/
8743
8744
/** Function that returns an iterable object over layers in the dataset.
8745
 *
8746
 * This is a C++ iterator friendly version of GetLayer().
8747
 *
8748
 * Typical use is:
8749
 * \code{.cpp}
8750
 * for( auto&& poLayer: poDS->GetLayers() )
8751
 * {
8752
 *       std::cout << "Layer  << poLayer->GetName() << std::endl;
8753
 * }
8754
 * \endcode
8755
 *
8756
 * @see GetLayer()
8757
 *
8758
 * @since GDAL 2.3
8759
 */
8760
GDALDataset::Layers GDALDataset::GetLayers()
8761
0
{
8762
0
    return Layers(this);
8763
0
}
8764
8765
/************************************************************************/
8766
/*                                 begin()                              */
8767
/************************************************************************/
8768
8769
/**
8770
 \brief Return beginning of layer iterator.
8771
8772
 @since GDAL 2.3
8773
*/
8774
8775
GDALDataset::Layers::Iterator GDALDataset::Layers::begin() const
8776
0
{
8777
0
    return {m_poSelf, true};
8778
0
}
8779
8780
/************************************************************************/
8781
/*                                  end()                               */
8782
/************************************************************************/
8783
8784
/**
8785
 \brief Return end of layer iterator.
8786
8787
 @since GDAL 2.3
8788
*/
8789
8790
GDALDataset::Layers::Iterator GDALDataset::Layers::end() const
8791
0
{
8792
0
    return {m_poSelf, false};
8793
0
}
8794
8795
/************************************************************************/
8796
/*                                  size()                             */
8797
/************************************************************************/
8798
8799
/**
8800
 \brief Get the number of layers in this dataset.
8801
8802
 @return layer count.
8803
8804
 @since GDAL 2.3
8805
*/
8806
8807
size_t GDALDataset::Layers::size() const
8808
0
{
8809
0
    return static_cast<size_t>(m_poSelf->GetLayerCount());
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[](int iLayer)
8829
0
{
8830
0
    return m_poSelf->GetLayer(iLayer);
8831
0
}
8832
8833
/************************************************************************/
8834
/*                                operator[]()                          */
8835
/************************************************************************/
8836
/**
8837
 \brief Fetch a layer by index.
8838
8839
 The returned layer remains owned by the
8840
 GDALDataset and should not be deleted by the application.
8841
8842
 @param iLayer a layer number between 0 and size()-1.
8843
8844
 @return the layer, or nullptr if iLayer is out of range or an error occurs.
8845
8846
 @since GDAL 2.3
8847
*/
8848
8849
OGRLayer *GDALDataset::Layers::operator[](size_t iLayer)
8850
0
{
8851
0
    return m_poSelf->GetLayer(static_cast<int>(iLayer));
8852
0
}
8853
8854
/************************************************************************/
8855
/*                                operator[]()                          */
8856
/************************************************************************/
8857
/**
8858
 \brief Fetch a layer by name.
8859
8860
 The returned layer remains owned by the
8861
 GDALDataset and should not be deleted by the application.
8862
8863
 @param pszLayerName layer name
8864
8865
 @return the layer, or nullptr if pszLayerName does not match with a layer
8866
8867
 @since GDAL 2.3
8868
*/
8869
8870
OGRLayer *GDALDataset::Layers::operator[](const char *pszLayerName)
8871
0
{
8872
0
    return m_poSelf->GetLayerByName(pszLayerName);
8873
0
}
8874
8875
/************************************************************************/
8876
/*               GDALDataset::Bands::Iterator::Private                 */
8877
/************************************************************************/
8878
8879
struct GDALDataset::Bands::Iterator::Private
8880
{
8881
    GDALRasterBand *m_poBand = nullptr;
8882
    int m_iCurBand = 0;
8883
    int m_nBandCount = 0;
8884
    GDALDataset *m_poDS = nullptr;
8885
};
8886
8887
GDALDataset::Bands::Iterator::Iterator(GDALDataset *poDS, bool bStart)
8888
0
    : m_poPrivate(new GDALDataset::Bands::Iterator::Private())
8889
0
{
8890
0
    m_poPrivate->m_poDS = poDS;
8891
0
    m_poPrivate->m_nBandCount = poDS->GetRasterCount();
8892
0
    if (bStart)
8893
0
    {
8894
0
        if (m_poPrivate->m_nBandCount)
8895
0
            m_poPrivate->m_poBand = poDS->GetRasterBand(1);
8896
0
    }
8897
0
    else
8898
0
    {
8899
0
        m_poPrivate->m_iCurBand = m_poPrivate->m_nBandCount;
8900
0
    }
8901
0
}
8902
8903
0
GDALDataset::Bands::Iterator::~Iterator() = default;
8904
8905
GDALRasterBand *GDALDataset::Bands::Iterator::operator*()
8906
0
{
8907
0
    return m_poPrivate->m_poBand;
8908
0
}
8909
8910
GDALDataset::Bands::Iterator &GDALDataset::Bands::Iterator::operator++()
8911
0
{
8912
0
    m_poPrivate->m_iCurBand++;
8913
0
    if (m_poPrivate->m_iCurBand < m_poPrivate->m_nBandCount)
8914
0
    {
8915
0
        m_poPrivate->m_poBand =
8916
0
            m_poPrivate->m_poDS->GetRasterBand(1 + m_poPrivate->m_iCurBand);
8917
0
    }
8918
0
    else
8919
0
    {
8920
0
        m_poPrivate->m_poBand = nullptr;
8921
0
    }
8922
0
    return *this;
8923
0
}
8924
8925
bool GDALDataset::Bands::Iterator::operator!=(const Iterator &it) const
8926
0
{
8927
0
    return m_poPrivate->m_iCurBand != it.m_poPrivate->m_iCurBand;
8928
0
}
8929
8930
/************************************************************************/
8931
/*                            GetBands()                           */
8932
/************************************************************************/
8933
8934
/** Function that returns an iterable object over GDALRasterBand in the dataset.
8935
 *
8936
 * This is a C++ iterator friendly version of GetRasterBand().
8937
 *
8938
 * Typical use is:
8939
 * \code{.cpp}
8940
 * for( auto&& poBand: poDS->GetBands() )
8941
 * {
8942
 *       std::cout << "Band  << poBand->GetDescription() << std::endl;
8943
 * }
8944
 * \endcode
8945
 *
8946
 * @see GetRasterBand()
8947
 *
8948
 * @since GDAL 2.3
8949
 */
8950
GDALDataset::Bands GDALDataset::GetBands()
8951
0
{
8952
0
    return Bands(this);
8953
0
}
8954
8955
/************************************************************************/
8956
/*                                 begin()                              */
8957
/************************************************************************/
8958
8959
/**
8960
 \brief Return beginning of band iterator.
8961
8962
 @since GDAL 2.3
8963
*/
8964
8965
const GDALDataset::Bands::Iterator GDALDataset::Bands::begin() const
8966
0
{
8967
0
    return {m_poSelf, true};
8968
0
}
8969
8970
/************************************************************************/
8971
/*                                  end()                               */
8972
/************************************************************************/
8973
8974
/**
8975
 \brief Return end of band iterator.
8976
8977
 @since GDAL 2.3
8978
*/
8979
8980
const GDALDataset::Bands::Iterator GDALDataset::Bands::end() const
8981
0
{
8982
0
    return {m_poSelf, false};
8983
0
}
8984
8985
/************************************************************************/
8986
/*                                  size()                             */
8987
/************************************************************************/
8988
8989
/**
8990
 \brief Get the number of raster bands in this dataset.
8991
8992
 @return raster band count.
8993
8994
 @since GDAL 2.3
8995
*/
8996
8997
size_t GDALDataset::Bands::size() const
8998
0
{
8999
0
    return static_cast<size_t>(m_poSelf->GetRasterCount());
9000
0
}
9001
9002
/************************************************************************/
9003
/*                                operator[]()                          */
9004
/************************************************************************/
9005
/**
9006
 \brief Fetch a raster band by index.
9007
9008
 The returned band remains owned by the
9009
 GDALDataset and should not be deleted by the application.
9010
9011
 @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9012
 consistent with the conventions of C/C++, i.e. starting at 0.
9013
9014
 @param iBand a band index between 0 and size()-1.
9015
9016
 @return the band, or nullptr if iBand is out of range or an error occurs.
9017
9018
 @since GDAL 2.3
9019
*/
9020
9021
GDALRasterBand *GDALDataset::Bands::operator[](int iBand)
9022
0
{
9023
0
    return m_poSelf->GetRasterBand(1 + iBand);
9024
0
}
9025
9026
/************************************************************************/
9027
/*                                operator[]()                          */
9028
/************************************************************************/
9029
9030
/**
9031
 \brief Fetch a raster band by index.
9032
9033
 The returned band remains owned by the
9034
 GDALDataset and should not be deleted by the application.
9035
9036
 @warning Contrary to GDALDataset::GetRasterBand(), the indexing here is
9037
 consistent with the conventions of C/C++, i.e. starting at 0.
9038
9039
 @param iBand a band index between 0 and size()-1.
9040
9041
 @return the band, or nullptr if iBand is out of range or an error occurs.
9042
9043
 @since GDAL 2.3
9044
*/
9045
9046
GDALRasterBand *GDALDataset::Bands::operator[](size_t iBand)
9047
0
{
9048
0
    return m_poSelf->GetRasterBand(1 + static_cast<int>(iBand));
9049
0
}
9050
9051
/************************************************************************/
9052
/*                           GetRootGroup()                             */
9053
/************************************************************************/
9054
9055
/**
9056
 \brief Return the root GDALGroup of this dataset.
9057
9058
 Only valid for multidimensional datasets.
9059
9060
 This is the same as the C function GDALDatasetGetRootGroup().
9061
9062
 @since GDAL 3.1
9063
*/
9064
9065
std::shared_ptr<GDALGroup> GDALDataset::GetRootGroup() const
9066
0
{
9067
0
    return nullptr;
9068
0
}
9069
9070
/************************************************************************/
9071
/*                        GetRawBinaryLayout()                          */
9072
/************************************************************************/
9073
9074
//! @cond Doxygen_Suppress
9075
/**
9076
 \brief Return the layout of a dataset that can be considered as a raw binary
9077
 format.
9078
9079
 @param sLayout Structure that will be set if the dataset is a raw binary one.
9080
 @return true if the dataset is a raw binary one.
9081
 @since GDAL 3.1
9082
*/
9083
9084
bool GDALDataset::GetRawBinaryLayout(RawBinaryLayout &sLayout)
9085
0
{
9086
0
    CPL_IGNORE_RET_VAL(sLayout);
9087
0
    return false;
9088
0
}
9089
9090
//! @endcond
9091
9092
/************************************************************************/
9093
/*                          ClearStatistics()                           */
9094
/************************************************************************/
9095
9096
/**
9097
 \brief Clear statistics
9098
9099
 Only implemented for now in PAM supported datasets
9100
9101
 This is the same as the C function GDALDatasetClearStatistics().
9102
9103
 @since GDAL 3.2
9104
*/
9105
9106
void GDALDataset::ClearStatistics()
9107
0
{
9108
0
    auto poRootGroup = GetRootGroup();
9109
0
    if (poRootGroup)
9110
0
        poRootGroup->ClearStatistics();
9111
0
}
9112
9113
/************************************************************************/
9114
/*                        GDALDatasetClearStatistics()                  */
9115
/************************************************************************/
9116
9117
/**
9118
 \brief Clear statistics
9119
9120
 This is the same as the C++ method GDALDataset::ClearStatistics().
9121
9122
 @since GDAL 3.2
9123
*/
9124
9125
void GDALDatasetClearStatistics(GDALDatasetH hDS)
9126
0
{
9127
0
    VALIDATE_POINTER0(hDS, __func__);
9128
0
    GDALDataset::FromHandle(hDS)->ClearStatistics();
9129
0
}
9130
9131
/************************************************************************/
9132
/*                        GetFieldDomainNames()                         */
9133
/************************************************************************/
9134
9135
/** Returns a list of the names of all field domains stored in the dataset.
9136
 *
9137
 * @note The default implementation assumes that drivers fully populate
9138
 * m_oMapFieldDomains when opening a dataset. If this assumption is incorrect
9139
 * then a specialized implementation of GetFieldDomainNames() must be
9140
 * implemented.
9141
 *
9142
 * @param papszOptions Driver specific options determining how attributes
9143
 * should be retrieved. Pass nullptr for default behavior.
9144
 *
9145
 * @return list of field domain names
9146
 * @since GDAL 3.5
9147
 */
9148
std::vector<std::string>
9149
GDALDataset::GetFieldDomainNames(CPL_UNUSED CSLConstList papszOptions) const
9150
0
{
9151
9152
0
    std::vector<std::string> names;
9153
0
    names.reserve(m_oMapFieldDomains.size());
9154
0
    for (const auto &it : m_oMapFieldDomains)
9155
0
    {
9156
0
        names.emplace_back(it.first);
9157
0
    }
9158
0
    return names;
9159
0
}
9160
9161
/************************************************************************/
9162
/*                      GDALDatasetGetFieldDomainNames()                */
9163
/************************************************************************/
9164
9165
/** Returns a list of the names of all field domains stored in the dataset.
9166
 *
9167
 * This is the same as the C++ method GDALDataset::GetFieldDomainNames().
9168
 *
9169
 * @param hDS Dataset handle.
9170
 * @param papszOptions Driver specific options determining how attributes
9171
 * should be retrieved. Pass nullptr for default behavior.
9172
 *
9173
 * @return list of field domain names, to be freed with CSLDestroy()
9174
 * @since GDAL 3.5
9175
 */
9176
char **GDALDatasetGetFieldDomainNames(GDALDatasetH hDS,
9177
                                      CSLConstList papszOptions)
9178
0
{
9179
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9180
0
    auto names =
9181
0
        GDALDataset::FromHandle(hDS)->GetFieldDomainNames(papszOptions);
9182
0
    CPLStringList res;
9183
0
    for (const auto &name : names)
9184
0
    {
9185
0
        res.AddString(name.c_str());
9186
0
    }
9187
0
    return res.StealList();
9188
0
}
9189
9190
/************************************************************************/
9191
/*                        GetFieldDomain()                              */
9192
/************************************************************************/
9193
9194
/** Get a field domain from its name.
9195
 *
9196
 * @return the field domain, or nullptr if not found.
9197
 * @since GDAL 3.3
9198
 */
9199
const OGRFieldDomain *GDALDataset::GetFieldDomain(const std::string &name) const
9200
0
{
9201
0
    const auto iter = m_oMapFieldDomains.find(name);
9202
0
    if (iter == m_oMapFieldDomains.end())
9203
0
        return nullptr;
9204
0
    return iter->second.get();
9205
0
}
9206
9207
/************************************************************************/
9208
/*                      GDALDatasetGetFieldDomain()                     */
9209
/************************************************************************/
9210
9211
/** Get a field domain from its name.
9212
 *
9213
 * This is the same as the C++ method GDALDataset::GetFieldDomain().
9214
 *
9215
 * @param hDS Dataset handle.
9216
 * @param pszName Name of field domain.
9217
 * @return the field domain (ownership remains to the dataset), or nullptr if
9218
 * not found.
9219
 * @since GDAL 3.3
9220
 */
9221
OGRFieldDomainH GDALDatasetGetFieldDomain(GDALDatasetH hDS, const char *pszName)
9222
0
{
9223
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9224
0
    VALIDATE_POINTER1(pszName, __func__, nullptr);
9225
0
    return OGRFieldDomain::ToHandle(const_cast<OGRFieldDomain *>(
9226
0
        GDALDataset::FromHandle(hDS)->GetFieldDomain(pszName)));
9227
0
}
9228
9229
/************************************************************************/
9230
/*                         AddFieldDomain()                             */
9231
/************************************************************************/
9232
9233
/** Add a field domain to the dataset.
9234
 *
9235
 * Only a few drivers will support this operation, and some of them might only
9236
 * support it only for some types of field domains.
9237
 * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9238
 * support this operation. A dataset having at least some support for this
9239
 * operation should report the ODsCAddFieldDomain dataset capability.
9240
 *
9241
 * Anticipated failures will not be emitted through the CPLError()
9242
 * infrastructure, but will be reported in the failureReason output parameter.
9243
 *
9244
 * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9245
 * default implementation of GetFieldDomainNames() to work correctly, or
9246
 * alternatively a specialized implementation of GetFieldDomainNames() should be
9247
 * implemented.
9248
 *
9249
 * @param domain The domain definition.
9250
 * @param failureReason      Output parameter. Will contain an error message if
9251
 *                           an error occurs.
9252
 * @return true in case of success.
9253
 * @since GDAL 3.3
9254
 */
9255
bool GDALDataset::AddFieldDomain(
9256
    CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9257
    std::string &failureReason)
9258
0
{
9259
0
    failureReason = "AddFieldDomain not supported by this driver";
9260
0
    return false;
9261
0
}
9262
9263
/************************************************************************/
9264
/*                     GDALDatasetAddFieldDomain()                      */
9265
/************************************************************************/
9266
9267
/** Add a field domain to the dataset.
9268
 *
9269
 * Only a few drivers will support this operation, and some of them might only
9270
 * support it only for some types of field domains.
9271
 * At the time of writing (GDAL 3.3), only the Memory and GeoPackage drivers
9272
 * support this operation. A dataset having at least some support for this
9273
 * operation should report the ODsCAddFieldDomain dataset capability.
9274
 *
9275
 * Anticipated failures will not be emitted through the CPLError()
9276
 * infrastructure, but will be reported in the ppszFailureReason output
9277
 * parameter.
9278
 *
9279
 * @param hDS                Dataset handle.
9280
 * @param hFieldDomain       The domain definition. Contrary to the C++ version,
9281
 *                           the passed object is copied.
9282
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9283
 *                           an error occurs (*ppszFailureReason to be freed
9284
 *                           with CPLFree). May be NULL.
9285
 * @return true in case of success.
9286
 * @since GDAL 3.3
9287
 */
9288
bool GDALDatasetAddFieldDomain(GDALDatasetH hDS, OGRFieldDomainH hFieldDomain,
9289
                               char **ppszFailureReason)
9290
0
{
9291
0
    VALIDATE_POINTER1(hDS, __func__, false);
9292
0
    VALIDATE_POINTER1(hFieldDomain, __func__, false);
9293
0
    auto poDomain = std::unique_ptr<OGRFieldDomain>(
9294
0
        OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9295
0
    if (poDomain == nullptr)
9296
0
        return false;
9297
0
    std::string failureReason;
9298
0
    const bool bRet = GDALDataset::FromHandle(hDS)->AddFieldDomain(
9299
0
        std::move(poDomain), failureReason);
9300
0
    if (ppszFailureReason)
9301
0
    {
9302
0
        *ppszFailureReason =
9303
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9304
0
    }
9305
0
    return bRet;
9306
0
}
9307
9308
/************************************************************************/
9309
/*                        DeleteFieldDomain()                           */
9310
/************************************************************************/
9311
9312
/** Removes a field domain from the dataset.
9313
 *
9314
 * Only a few drivers will support this operation.
9315
 *
9316
 * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9317
 * support this operation. A dataset having at least some support for this
9318
 * operation should report the ODsCDeleteFieldDomain dataset capability.
9319
 *
9320
 * Anticipated failures will not be emitted through the CPLError()
9321
 * infrastructure, but will be reported in the failureReason output parameter.
9322
 *
9323
 * @note Drivers should make sure to update m_oMapFieldDomains in order for the
9324
 * default implementation of GetFieldDomainNames() to work correctly, or
9325
 * alternatively a specialized implementation of GetFieldDomainNames() should be
9326
 * implemented.
9327
 *
9328
 * @param name The domain name.
9329
 * @param failureReason      Output parameter. Will contain an error message if
9330
 *                           an error occurs.
9331
 * @return true in case of success.
9332
 * @since GDAL 3.5
9333
 */
9334
bool GDALDataset::DeleteFieldDomain(CPL_UNUSED const std::string &name,
9335
                                    std::string &failureReason)
9336
0
{
9337
0
    failureReason = "DeleteFieldDomain not supported by this driver";
9338
0
    return false;
9339
0
}
9340
9341
/************************************************************************/
9342
/*                  GDALDatasetDeleteFieldDomain()                      */
9343
/************************************************************************/
9344
9345
/** Removes a field domain from the dataset.
9346
 *
9347
 * Only a few drivers will support this operation.
9348
 *
9349
 * At the time of writing (GDAL 3.5), only the Memory and GeoPackage drivers
9350
 * support this operation. A dataset having at least some support for this
9351
 * operation should report the ODsCDeleteFieldDomain dataset capability.
9352
 *
9353
 * Anticipated failures will not be emitted through the CPLError()
9354
 * infrastructure, but will be reported in the ppszFailureReason output
9355
 * parameter.
9356
 *
9357
 * @param hDS                Dataset handle.
9358
 * @param pszName            The domain name.
9359
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9360
 *                           an error occurs (*ppszFailureReason to be freed
9361
 *                           with CPLFree). May be NULL.
9362
 * @return true in case of success.
9363
 * @since GDAL 3.3
9364
 */
9365
bool GDALDatasetDeleteFieldDomain(GDALDatasetH hDS, const char *pszName,
9366
                                  char **ppszFailureReason)
9367
0
{
9368
0
    VALIDATE_POINTER1(hDS, __func__, false);
9369
0
    VALIDATE_POINTER1(pszName, __func__, false);
9370
0
    std::string failureReason;
9371
0
    const bool bRet =
9372
0
        GDALDataset::FromHandle(hDS)->DeleteFieldDomain(pszName, failureReason);
9373
0
    if (ppszFailureReason)
9374
0
    {
9375
0
        *ppszFailureReason =
9376
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9377
0
    }
9378
0
    return bRet;
9379
0
}
9380
9381
/************************************************************************/
9382
/*                       UpdateFieldDomain()                            */
9383
/************************************************************************/
9384
9385
/** Updates an existing field domain by replacing its definition.
9386
 *
9387
 * The existing field domain with matching name will be replaced.
9388
 *
9389
 * Only a few drivers will support this operation, and some of them might only
9390
 * support it only for some types of field domains.
9391
 * At the time of writing (GDAL 3.5), only the Memory driver
9392
 * supports this operation. A dataset having at least some support for this
9393
 * operation should report the ODsCUpdateFieldDomain dataset capability.
9394
 *
9395
 * Anticipated failures will not be emitted through the CPLError()
9396
 * infrastructure, but will be reported in the failureReason output parameter.
9397
 *
9398
 * @param domain The domain definition.
9399
 * @param failureReason      Output parameter. Will contain an error message if
9400
 *                           an error occurs.
9401
 * @return true in case of success.
9402
 * @since GDAL 3.5
9403
 */
9404
bool GDALDataset::UpdateFieldDomain(
9405
    CPL_UNUSED std::unique_ptr<OGRFieldDomain> &&domain,
9406
    std::string &failureReason)
9407
0
{
9408
0
    failureReason = "UpdateFieldDomain not supported by this driver";
9409
0
    return false;
9410
0
}
9411
9412
/************************************************************************/
9413
/*                  GDALDatasetUpdateFieldDomain()                      */
9414
/************************************************************************/
9415
9416
/** Updates an existing field domain by replacing its definition.
9417
 *
9418
 * The existing field domain with matching name will be replaced.
9419
 *
9420
 * Only a few drivers will support this operation, and some of them might only
9421
 * support it only for some types of field domains.
9422
 * At the time of writing (GDAL 3.5), only the Memory driver
9423
 * supports this operation. A dataset having at least some support for this
9424
 * operation should report the ODsCUpdateFieldDomain dataset capability.
9425
 *
9426
 * Anticipated failures will not be emitted through the CPLError()
9427
 * infrastructure, but will be reported in the failureReason output parameter.
9428
 *
9429
 * @param hDS                Dataset handle.
9430
 * @param hFieldDomain       The domain definition. Contrary to the C++ version,
9431
 *                           the passed object is copied.
9432
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9433
 *                           an error occurs (*ppszFailureReason to be freed
9434
 *                           with CPLFree). May be NULL.
9435
 * @return true in case of success.
9436
 * @since GDAL 3.5
9437
 */
9438
bool GDALDatasetUpdateFieldDomain(GDALDatasetH hDS,
9439
                                  OGRFieldDomainH hFieldDomain,
9440
                                  char **ppszFailureReason)
9441
0
{
9442
0
    VALIDATE_POINTER1(hDS, __func__, false);
9443
0
    VALIDATE_POINTER1(hFieldDomain, __func__, false);
9444
0
    auto poDomain = std::unique_ptr<OGRFieldDomain>(
9445
0
        OGRFieldDomain::FromHandle(hFieldDomain)->Clone());
9446
0
    if (poDomain == nullptr)
9447
0
        return false;
9448
0
    std::string failureReason;
9449
0
    const bool bRet = GDALDataset::FromHandle(hDS)->UpdateFieldDomain(
9450
0
        std::move(poDomain), failureReason);
9451
0
    if (ppszFailureReason)
9452
0
    {
9453
0
        *ppszFailureReason =
9454
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9455
0
    }
9456
0
    return bRet;
9457
0
}
9458
9459
/************************************************************************/
9460
/*                        GetRelationshipNames()                        */
9461
/************************************************************************/
9462
9463
/** Returns a list of the names of all relationships stored in the dataset.
9464
 *
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
9469
 * @since GDAL 3.6
9470
 */
9471
std::vector<std::string>
9472
GDALDataset::GetRelationshipNames(CPL_UNUSED CSLConstList papszOptions) const
9473
0
{
9474
0
    return {};
9475
0
}
9476
9477
/************************************************************************/
9478
/*                     GDALDatasetGetRelationshipNames()                */
9479
/************************************************************************/
9480
9481
/** Returns a list of the names of all relationships stored in the dataset.
9482
 *
9483
 * This is the same as the C++ method GDALDataset::GetRelationshipNames().
9484
 *
9485
 * @param hDS Dataset handle.
9486
 * @param papszOptions Driver specific options determining how relationships
9487
 * should be retrieved. Pass nullptr for default behavior.
9488
 *
9489
 * @return list of relationship names, to be freed with CSLDestroy()
9490
 * @since GDAL 3.6
9491
 */
9492
char **GDALDatasetGetRelationshipNames(GDALDatasetH hDS,
9493
                                       CSLConstList papszOptions)
9494
0
{
9495
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9496
0
    auto names =
9497
0
        GDALDataset::FromHandle(hDS)->GetRelationshipNames(papszOptions);
9498
0
    CPLStringList res;
9499
0
    for (const auto &name : names)
9500
0
    {
9501
0
        res.AddString(name.c_str());
9502
0
    }
9503
0
    return res.StealList();
9504
0
}
9505
9506
/************************************************************************/
9507
/*                        GetRelationship()                             */
9508
/************************************************************************/
9509
9510
/** Get a relationship from its name.
9511
 *
9512
 * @return the relationship, or nullptr if not found.
9513
 * @since GDAL 3.6
9514
 */
9515
const GDALRelationship *
9516
GDALDataset::GetRelationship(CPL_UNUSED const std::string &name) const
9517
0
{
9518
0
    return nullptr;
9519
0
}
9520
9521
/************************************************************************/
9522
/*                      GDALDatasetGetRelationship()                    */
9523
/************************************************************************/
9524
9525
/** Get a relationship from its name.
9526
 *
9527
 * This is the same as the C++ method GDALDataset::GetRelationship().
9528
 *
9529
 * @param hDS Dataset handle.
9530
 * @param pszName Name of relationship.
9531
 * @return the relationship (ownership remains to the dataset), or nullptr if
9532
 * not found.
9533
 * @since GDAL 3.6
9534
 */
9535
GDALRelationshipH GDALDatasetGetRelationship(GDALDatasetH hDS,
9536
                                             const char *pszName)
9537
0
{
9538
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9539
0
    VALIDATE_POINTER1(pszName, __func__, nullptr);
9540
0
    return GDALRelationship::ToHandle(const_cast<GDALRelationship *>(
9541
0
        GDALDataset::FromHandle(hDS)->GetRelationship(pszName)));
9542
0
}
9543
9544
/************************************************************************/
9545
/*                         AddRelationship()                            */
9546
/************************************************************************/
9547
9548
/** Add a relationship to the dataset.
9549
 *
9550
 * Only a few drivers will support this operation, and some of them might only
9551
 * support it only for some types of relationships.
9552
 *
9553
 * A dataset having at least some support for this
9554
 * operation should report the GDsCAddRelationship dataset capability.
9555
 *
9556
 * Anticipated failures will not be emitted through the CPLError()
9557
 * infrastructure, but will be reported in the failureReason output parameter.
9558
 *
9559
 * When adding a many-to-many relationship
9560
 * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9561
 * mapping table name (see GDALRelationship::GetMappingTableName) to instruct
9562
 * the driver to create an appropriately named and structured mapping table.
9563
 * Some dataset formats require particular naming conventions and field
9564
 * structures for the mapping table, and delegating the construction of the
9565
 * mapping table to the driver will avoid these pitfalls.
9566
 *
9567
 * @param relationship The relationship definition.
9568
 * @param failureReason      Output parameter. Will contain an error message if
9569
 *                           an error occurs.
9570
 * @return true in case of success.
9571
 * @since GDAL 3.6
9572
 */
9573
bool GDALDataset::AddRelationship(
9574
    CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9575
    std::string &failureReason)
9576
0
{
9577
0
    failureReason = "AddRelationship not supported by this driver";
9578
0
    return false;
9579
0
}
9580
9581
/************************************************************************/
9582
/*                     GDALDatasetAddRelationship()                     */
9583
/************************************************************************/
9584
9585
/** Add a relationship to the dataset.
9586
 *
9587
 * Only a few drivers will support this operation, and some of them might only
9588
 * support it only for some types of relationships.
9589
 *
9590
 * A dataset having at least some support for this
9591
 * operation should report the GDsCAddRelationship dataset capability.
9592
 *
9593
 * Anticipated failures will not be emitted through the CPLError()
9594
 * infrastructure, but will be reported in the failureReason output parameter.
9595
 *
9596
 * When adding a many-to-many relationship
9597
 * (GDALRelationshipCardinality::GRC_MANY_TO_MANY), it is possible to omit the
9598
 * mapping table name (see GDALRelationshipGetMappingTableName) to instruct the
9599
 * driver to create an appropriately named and structured mapping table. Some
9600
 * dataset formats require particular naming conventions and field structures
9601
 * for the mapping table, and delegating the construction of the mapping table
9602
 * to the driver will avoid these pitfalls.
9603
 *
9604
 * @param hDS                Dataset handle.
9605
 * @param hRelationship      The relationship definition. Contrary to the C++
9606
 * version, the passed object is copied.
9607
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9608
 *                           an error occurs (*ppszFailureReason to be freed
9609
 *                           with CPLFree). May be NULL.
9610
 * @return true in case of success.
9611
 * @since GDAL 3.6
9612
 */
9613
bool GDALDatasetAddRelationship(GDALDatasetH hDS,
9614
                                GDALRelationshipH hRelationship,
9615
                                char **ppszFailureReason)
9616
0
{
9617
0
    VALIDATE_POINTER1(hDS, __func__, false);
9618
0
    VALIDATE_POINTER1(hRelationship, __func__, false);
9619
0
    std::unique_ptr<GDALRelationship> poRelationship(
9620
0
        new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9621
0
    std::string failureReason;
9622
0
    const bool bRet = GDALDataset::FromHandle(hDS)->AddRelationship(
9623
0
        std::move(poRelationship), failureReason);
9624
0
    if (ppszFailureReason)
9625
0
    {
9626
0
        *ppszFailureReason =
9627
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9628
0
    }
9629
0
    return bRet;
9630
0
}
9631
9632
/************************************************************************/
9633
/*                        DeleteRelationship()                          */
9634
/************************************************************************/
9635
9636
/** Removes a relationship from the dataset.
9637
 *
9638
 * Only a few drivers will support this operation.
9639
 *
9640
 * A dataset having at least some support for this
9641
 * operation should report the GDsCDeleteRelationship dataset capability.
9642
 *
9643
 * Anticipated failures will not be emitted through the CPLError()
9644
 * infrastructure, but will be reported in the failureReason output parameter.
9645
 *
9646
 * @param name The relationship name.
9647
 * @param failureReason      Output parameter. Will contain an error message if
9648
 *                           an error occurs.
9649
 * @return true in case of success.
9650
 * @since GDAL 3.6
9651
 */
9652
bool GDALDataset::DeleteRelationship(CPL_UNUSED const std::string &name,
9653
                                     std::string &failureReason)
9654
0
{
9655
0
    failureReason = "DeleteRelationship not supported by this driver";
9656
0
    return false;
9657
0
}
9658
9659
/************************************************************************/
9660
/*                  GDALDatasetDeleteRelationship()                     */
9661
/************************************************************************/
9662
9663
/** Removes a relationship from the dataset.
9664
 *
9665
 * Only a few drivers will support this operation.
9666
 *
9667
 * A dataset having at least some support for this
9668
 * operation should report the GDsCDeleteRelationship dataset capability.
9669
 *
9670
 * Anticipated failures will not be emitted through the CPLError()
9671
 * infrastructure, but will be reported in the ppszFailureReason output
9672
 * parameter.
9673
 *
9674
 * @param hDS                Dataset handle.
9675
 * @param pszName            The relationship name.
9676
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9677
 *                           an error occurs (*ppszFailureReason to be freed
9678
 *                           with CPLFree). May be NULL.
9679
 * @return true in case of success.
9680
 * @since GDAL 3.6
9681
 */
9682
bool GDALDatasetDeleteRelationship(GDALDatasetH hDS, const char *pszName,
9683
                                   char **ppszFailureReason)
9684
0
{
9685
0
    VALIDATE_POINTER1(hDS, __func__, false);
9686
0
    VALIDATE_POINTER1(pszName, __func__, false);
9687
0
    std::string failureReason;
9688
0
    const bool bRet = GDALDataset::FromHandle(hDS)->DeleteRelationship(
9689
0
        pszName, failureReason);
9690
0
    if (ppszFailureReason)
9691
0
    {
9692
0
        *ppszFailureReason =
9693
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9694
0
    }
9695
0
    return bRet;
9696
0
}
9697
9698
/************************************************************************/
9699
/*                       UpdateRelationship()                           */
9700
/************************************************************************/
9701
9702
/** Updates an existing relationship by replacing its definition.
9703
 *
9704
 * The existing relationship with matching name will be replaced.
9705
 *
9706
 * Only a few drivers will support this operation, and some of them might only
9707
 * support it only for some types of relationships.
9708
 * A dataset having at least some support for this
9709
 * operation should report the GDsCUpdateRelationship dataset capability.
9710
 *
9711
 * Anticipated failures will not be emitted through the CPLError()
9712
 * infrastructure, but will be reported in the failureReason output parameter.
9713
 *
9714
 * @param relationship   The relationship definition.
9715
 * @param failureReason  Output parameter. Will contain an error message if
9716
 *                       an error occurs.
9717
 * @return true in case of success.
9718
 * @since GDAL 3.6
9719
 */
9720
bool GDALDataset::UpdateRelationship(
9721
    CPL_UNUSED std::unique_ptr<GDALRelationship> &&relationship,
9722
    std::string &failureReason)
9723
0
{
9724
0
    failureReason = "UpdateRelationship not supported by this driver";
9725
0
    return false;
9726
0
}
9727
9728
/************************************************************************/
9729
/*                  GDALDatasetUpdateRelationship()                     */
9730
/************************************************************************/
9731
9732
/** Updates an existing relationship by replacing its definition.
9733
 *
9734
 * The existing relationship with matching name will be replaced.
9735
 *
9736
 * Only a few drivers will support this operation, and some of them might only
9737
 * support it only for some types of relationships.
9738
 * A dataset having at least some support for this
9739
 * operation should report the GDsCUpdateRelationship dataset capability.
9740
 *
9741
 * Anticipated failures will not be emitted through the CPLError()
9742
 * infrastructure, but will be reported in the failureReason output parameter.
9743
 *
9744
 * @param hDS                Dataset handle.
9745
 * @param hRelationship      The relationship definition. Contrary to the C++
9746
 * version, the passed object is copied.
9747
 * @param ppszFailureReason  Output parameter. Will contain an error message if
9748
 *                           an error occurs (*ppszFailureReason to be freed
9749
 *                           with CPLFree). May be NULL.
9750
 * @return true in case of success.
9751
 * @since GDAL 3.5
9752
 */
9753
bool GDALDatasetUpdateRelationship(GDALDatasetH hDS,
9754
                                   GDALRelationshipH hRelationship,
9755
                                   char **ppszFailureReason)
9756
0
{
9757
0
    VALIDATE_POINTER1(hDS, __func__, false);
9758
0
    VALIDATE_POINTER1(hRelationship, __func__, false);
9759
0
    std::unique_ptr<GDALRelationship> poRelationship(
9760
0
        new GDALRelationship(*GDALRelationship::FromHandle(hRelationship)));
9761
0
    std::string failureReason;
9762
0
    const bool bRet = GDALDataset::FromHandle(hDS)->UpdateRelationship(
9763
0
        std::move(poRelationship), failureReason);
9764
0
    if (ppszFailureReason)
9765
0
    {
9766
0
        *ppszFailureReason =
9767
0
            failureReason.empty() ? nullptr : CPLStrdup(failureReason.c_str());
9768
0
    }
9769
0
    return bRet;
9770
0
}
9771
9772
/************************************************************************/
9773
/*                  GDALDatasetSetQueryLoggerFunc()                     */
9774
/************************************************************************/
9775
9776
/**
9777
 * Sets the SQL query logger callback.
9778
 *
9779
 * When supported by the driver, the callback will be called with
9780
 * the executed SQL text, the error message, the execution time in milliseconds,
9781
 * the number of records fetched/affected and the client status data.
9782
 *
9783
 * A value of -1 in the execution time or in the number of records indicates
9784
 * that the values are unknown.
9785
 *
9786
 * @param hDS                   Dataset handle.
9787
 * @param pfnQueryLoggerFunc    Callback function
9788
 * @param poQueryLoggerArg      Opaque client status data
9789
 * @return                      true in case of success.
9790
 * @since                       GDAL 3.7
9791
 */
9792
bool GDALDatasetSetQueryLoggerFunc(GDALDatasetH hDS,
9793
                                   GDALQueryLoggerFunc pfnQueryLoggerFunc,
9794
                                   void *poQueryLoggerArg)
9795
0
{
9796
0
    VALIDATE_POINTER1(hDS, __func__, false);
9797
0
    return GDALDataset::FromHandle(hDS)->SetQueryLoggerFunc(pfnQueryLoggerFunc,
9798
0
                                                            poQueryLoggerArg);
9799
0
}
9800
9801
//! @cond Doxygen_Suppress
9802
9803
/************************************************************************/
9804
/*                       SetEnableOverviews()                           */
9805
/************************************************************************/
9806
9807
void GDALDataset::SetEnableOverviews(bool bEnable)
9808
0
{
9809
0
    if (m_poPrivate)
9810
0
    {
9811
0
        m_poPrivate->m_bOverviewsEnabled = bEnable;
9812
0
    }
9813
0
}
9814
9815
/************************************************************************/
9816
/*                      AreOverviewsEnabled()                           */
9817
/************************************************************************/
9818
9819
bool GDALDataset::AreOverviewsEnabled() const
9820
0
{
9821
0
    return m_poPrivate ? m_poPrivate->m_bOverviewsEnabled : true;
9822
0
}
9823
9824
/************************************************************************/
9825
/*                             IsAllBands()                             */
9826
/************************************************************************/
9827
9828
bool GDALDataset::IsAllBands(int nBandCount, const int *panBandList) const
9829
0
{
9830
0
    if (nBands != nBandCount)
9831
0
        return false;
9832
0
    if (panBandList)
9833
0
    {
9834
0
        for (int i = 0; i < nBandCount; ++i)
9835
0
        {
9836
0
            if (panBandList[i] != i + 1)
9837
0
                return false;
9838
0
        }
9839
0
    }
9840
0
    return true;
9841
0
}
9842
9843
//! @endcond
9844
9845
/************************************************************************/
9846
/*                       GetCompressionFormats()                        */
9847
/************************************************************************/
9848
9849
/** Return the compression formats that can be natively obtained for the
9850
 * window of interest and requested bands.
9851
 *
9852
 * For example, a tiled dataset may be able to return data in a compressed
9853
 * format if the window of interest matches exactly a tile. For some formats,
9854
 * drivers may also be able to merge several tiles together (not currently
9855
 * implemented though).
9856
 *
9857
 * Each format string is a pseudo MIME type, whose first part can be passed
9858
 * as the pszFormat argument of ReadCompressedData(), with additional
9859
 * parameters specified as key=value with a semi-colon separator.
9860
 *
9861
 * The amount and types of optional parameters passed after the MIME type is
9862
 * format dependent, and driver dependent (some drivers might not be able to
9863
 * return those extra information without doing a rather costly processing).
9864
 *
9865
 * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9866
 * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9867
 * consequently "JPEG" can be passed as the pszFormat argument of
9868
 * ReadCompressedData(). For JPEG, implementations can use the
9869
 * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9870
 * above from a JPEG codestream.
9871
 *
9872
 * Several values might be returned. For example,
9873
 * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9874
 * if the JPEGXL codestream includes a JPEG reconstruction box.
9875
 *
9876
 * In the general case this method will return an empty list.
9877
 *
9878
 * This is the same as C function GDALDatasetGetCompressionFormats().
9879
 *
9880
 * @param nXOff The pixel offset to the top left corner of the region
9881
 * of the band to be accessed.  This would be zero to start from the left side.
9882
 *
9883
 * @param nYOff The line offset to the top left corner of the region
9884
 * of the band to be accessed.  This would be zero to start from the top.
9885
 *
9886
 * @param nXSize The width of the region of the band to be accessed in pixels.
9887
 *
9888
 * @param nYSize The height of the region of the band to be accessed in lines.
9889
 *
9890
 * @param nBandCount the number of bands being requested.
9891
 *
9892
 * @param panBandList the list of nBandCount band numbers.
9893
 * Note band numbers are 1 based. This may be NULL to select the first
9894
 * nBandCount bands.
9895
 *
9896
 * @return a list of compatible formats (which may be empty)
9897
 *
9898
 * For example, to check if native compression format(s) are available on the
9899
 * whole image:
9900
 * \code{.cpp}
9901
 *   const CPLStringList aosFormats =
9902
 *      poDataset->GetCompressionFormats(0, 0,
9903
 *                                       poDataset->GetRasterXSize(),
9904
 *                                       poDataset->GetRasterYSize(),
9905
 *                                       poDataset->GetRasterCount(),
9906
 *                                       nullptr);
9907
 *   for( const char* pszFormat: aosFormats )
9908
 *   {
9909
 *      // Remove optional parameters and just print out the MIME type.
9910
 *      const CPLStringList aosTokens(CSLTokenizeString2(pszFormat, ";", 0));
9911
 *      printf("Found format %s\n, aosTokens[0]);
9912
 *   }
9913
 * \endcode
9914
 *
9915
 * @since GDAL 3.7
9916
 */
9917
CPLStringList
9918
GDALDataset::GetCompressionFormats(CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
9919
                                   CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
9920
                                   CPL_UNUSED int nBandCount,
9921
                                   CPL_UNUSED const int *panBandList)
9922
0
{
9923
0
    return CPLStringList();
9924
0
}
9925
9926
/************************************************************************/
9927
/*                 GDALDatasetGetCompressionFormats()                   */
9928
/************************************************************************/
9929
9930
/** Return the compression formats that can be natively obtained for the
9931
 * window of interest and requested bands.
9932
 *
9933
 * For example, a tiled dataset may be able to return data in a compressed
9934
 * format if the window of interest matches exactly a tile. For some formats,
9935
 * drivers may also be able to merge several tiles together (not currently
9936
 * implemented though).
9937
 *
9938
 * Each format string is a pseudo MIME type, whose first part can be passed
9939
 * as the pszFormat argument of ReadCompressedData(), with additional
9940
 * parameters specified as key=value with a semi-colon separator.
9941
 *
9942
 * The amount and types of optional parameters passed after the MIME type is
9943
 * format dependent, and driver dependent (some drivers might not be able to
9944
 * return those extra information without doing a rather costly processing).
9945
 *
9946
 * For example, a driver might return "JPEG;frame_type=SOF0_baseline;"
9947
 * "bit_depth=8;num_components=3;subsampling=4:2:0;colorspace=YCbCr", and
9948
 * consequently "JPEG" can be passed as the pszFormat argument of
9949
 * ReadCompressedData(). For JPEG, implementations can use the
9950
 * GDALGetCompressionFormatForJPEG() helper method to generate a string like
9951
 * above from a JPEG codestream.
9952
 *
9953
 * Several values might be returned. For example,
9954
 * the JPEGXL driver will return "JXL", but also potentially "JPEG"
9955
 * if the JPEGXL codestream includes a JPEG reconstruction box.
9956
 *
9957
 * In the general case this method will return an empty list.
9958
 *
9959
 * This is the same as C++ method GDALDataset::GetCompressionFormats().
9960
 *
9961
 * @param hDS Dataset handle.
9962
 *
9963
 * @param nXOff The pixel offset to the top left corner of the region
9964
 * of the band to be accessed.  This would be zero to start from the left side.
9965
 *
9966
 * @param nYOff The line offset to the top left corner of the region
9967
 * of the band to be accessed.  This would be zero to start from the top.
9968
 *
9969
 * @param nXSize The width of the region of the band to be accessed in pixels.
9970
 *
9971
 * @param nYSize The height of the region of the band to be accessed in lines.
9972
 *
9973
 * @param nBandCount the number of bands being requested.
9974
 *
9975
 * @param panBandList the list of nBandCount band numbers.
9976
 * Note band numbers are 1 based. This may be NULL to select the first
9977
 * nBandCount bands.
9978
 *
9979
 * @return a list of compatible formats (which may be empty) that should be
9980
 * freed with CSLDestroy(), or nullptr.
9981
 *
9982
 * @since GDAL 3.7
9983
 */
9984
char **GDALDatasetGetCompressionFormats(GDALDatasetH hDS, int nXOff, int nYOff,
9985
                                        int nXSize, int nYSize, int nBandCount,
9986
                                        const int *panBandList)
9987
0
{
9988
0
    VALIDATE_POINTER1(hDS, __func__, nullptr);
9989
0
    return GDALDataset::FromHandle(hDS)
9990
0
        ->GetCompressionFormats(nXOff, nYOff, nXSize, nYSize, nBandCount,
9991
0
                                panBandList)
9992
0
        .StealList();
9993
0
}
9994
9995
/************************************************************************/
9996
/*                         ReadCompressedData()                         */
9997
/************************************************************************/
9998
9999
/** Return the compressed content that can be natively obtained for the
10000
 * window of interest and requested bands.
10001
 *
10002
 * For example, a tiled dataset may be able to return data in compressed format
10003
 * if the window of interest matches exactly a tile. For some formats, drivers
10004
 * may also be example to merge several tiles together (not currently
10005
 * implemented though).
10006
 *
10007
 * The implementation should make sure that the content returned forms a valid
10008
 * standalone file. For example, for the GeoTIFF implementation of this method,
10009
 * when extracting a JPEG tile, the method will automatically add the content
10010
 * of the JPEG Huffman and/or quantization tables that might be stored in the
10011
 * TIFF JpegTables tag, and not in tile data itself.
10012
 *
10013
 * In the general case this method will return CE_Failure.
10014
 *
10015
 * This is the same as C function GDALDatasetReadCompressedData().
10016
 *
10017
 * @param pszFormat Requested compression format (e.g. "JPEG",
10018
 * "WEBP", "JXL"). This is the MIME type of one of the values
10019
 * returned by GetCompressionFormats(). The format string is designed to
10020
 * potentially include at a later point key=value optional parameters separated
10021
 * by a semi-colon character. At time of writing, none are implemented.
10022
 * ReadCompressedData() implementations should verify optional parameters and
10023
 * return CE_Failure if they cannot support one of them.
10024
 *
10025
 * @param nXOff The pixel offset to the top left corner of the region
10026
 * of the band to be accessed.  This would be zero to start from the left side.
10027
 *
10028
 * @param nYOff The line offset to the top left corner of the region
10029
 * of the band to be accessed.  This would be zero to start from the top.
10030
 *
10031
 * @param nXSize The width of the region of the band to be accessed in pixels.
10032
 *
10033
 * @param nYSize The height of the region of the band to be accessed in lines.
10034
 *
10035
 * @param nBandCount the number of bands being requested.
10036
 *
10037
 * @param panBandList the list of nBandCount band numbers.
10038
 * Note band numbers are 1 based. This may be NULL to select the first
10039
 * nBandCount bands.
10040
 *
10041
 * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10042
 * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10043
 * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10044
 * buffer will be filled with the compressed data, provided that pnBufferSize
10045
 * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10046
 * of *ppBuffer, is sufficiently large to hold the data.
10047
 * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10048
 * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10049
 * free it with VSIFree().
10050
 * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10051
 * but *pnBufferSize will be updated with an upper bound of the size that would
10052
 * be necessary to hold it (if pnBufferSize != nullptr).
10053
 *
10054
 * @param pnBufferSize Output buffer size, or nullptr.
10055
 * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10056
 * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10057
 * method is successful, *pnBufferSize will be updated with the actual size
10058
 * used.
10059
 *
10060
 * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10061
 * If ppszDetailedFormat is not nullptr, then, on success, the method will
10062
 * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10063
 * *ppszDetailedFormat might contain strings like
10064
 * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10065
 * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10066
 * The string will contain at least as much information as what
10067
 * GetCompressionFormats() returns, and potentially more when
10068
 * ppBuffer != nullptr.
10069
 *
10070
 * @return CE_None in case of success, CE_Failure otherwise.
10071
 *
10072
 * For example, to request JPEG content on the whole image and let GDAL deal
10073
 * with the buffer allocation.
10074
 * \code{.cpp}
10075
 *   void* pBuffer = nullptr;
10076
 *   size_t nBufferSize = 0;
10077
 *   CPLErr eErr =
10078
 *      poDataset->ReadCompressedData("JPEG",
10079
 *                                    0, 0,
10080
 *                                    poDataset->GetRasterXSize(),
10081
 *                                    poDataset->GetRasterYSize(),
10082
 *                                    poDataset->GetRasterCount(),
10083
 *                                    nullptr, // panBandList
10084
 *                                    &pBuffer,
10085
 *                                    &nBufferSize,
10086
 *                                    nullptr // ppszDetailedFormat
10087
 *                                   );
10088
 *   if (eErr == CE_None)
10089
 *   {
10090
 *       CPLAssert(pBuffer != nullptr);
10091
 *       CPLAssert(nBufferSize > 0);
10092
 *       VSILFILE* fp = VSIFOpenL("my.jpeg", "wb");
10093
 *       if (fp)
10094
 *       {
10095
 *           VSIFWriteL(pBuffer, nBufferSize, 1, fp);
10096
 *           VSIFCloseL(fp);
10097
 *       }
10098
 *       VSIFree(pBuffer);
10099
 *   }
10100
 * \endcode
10101
 *
10102
 * Or to manage the buffer allocation on your side:
10103
 * \code{.cpp}
10104
 *   size_t nUpperBoundBufferSize = 0;
10105
 *   CPLErr eErr =
10106
 *      poDataset->ReadCompressedData("JPEG",
10107
 *                                    0, 0,
10108
 *                                    poDataset->GetRasterXSize(),
10109
 *                                    poDataset->GetRasterYSize(),
10110
 *                                    poDataset->GetRasterCount(),
10111
 *                                    nullptr, // panBandList
10112
 *                                    nullptr, // ppBuffer,
10113
 *                                    &nUpperBoundBufferSize,
10114
 *                                    nullptr // ppszDetailedFormat
10115
 *                                   );
10116
 *   if (eErr == CE_None)
10117
 *   {
10118
 *       std::vector<uint8_t> myBuffer;
10119
 *       myBuffer.resize(nUpperBoundBufferSize);
10120
 *       void* pBuffer = myBuffer.data();
10121
 *       size_t nActualSize = nUpperBoundBufferSize;
10122
 *       char* pszDetailedFormat = nullptr;
10123
 *       // We also request detailed format, but we could have passed it to
10124
 *       // nullptr as well.
10125
 *       eErr =
10126
 *         poDataset->ReadCompressedData("JPEG",
10127
 *                                       0, 0,
10128
 *                                       poDataset->GetRasterXSize(),
10129
 *                                       poDataset->GetRasterYSize(),
10130
 *                                       poDataset->GetRasterCount(),
10131
 *                                       nullptr, // panBandList
10132
 *                                       &pBuffer,
10133
 *                                       &nActualSize,
10134
 *                                       &pszDetailedFormat);
10135
 *       if (eErr == CE_None)
10136
 *       {
10137
 *          CPLAssert(pBuffer == myBuffer.data()); // pointed value not modified
10138
 *          CPLAssert(nActualSize <= nUpperBoundBufferSize);
10139
 *          myBuffer.resize(nActualSize);
10140
 *          // do something useful
10141
 *          VSIFree(pszDetailedFormat);
10142
 *       }
10143
 *   }
10144
 * \endcode
10145
 *
10146
 * @since GDAL 3.7
10147
 */
10148
CPLErr GDALDataset::ReadCompressedData(
10149
    CPL_UNUSED const char *pszFormat, CPL_UNUSED int nXOff,
10150
    CPL_UNUSED int nYOff, CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
10151
    CPL_UNUSED int nBandCount, CPL_UNUSED const int *panBandList,
10152
    CPL_UNUSED void **ppBuffer, CPL_UNUSED size_t *pnBufferSize,
10153
    CPL_UNUSED char **ppszDetailedFormat)
10154
0
{
10155
0
    return CE_Failure;
10156
0
}
10157
10158
/************************************************************************/
10159
/*                  GDALDatasetReadCompressedData()                     */
10160
/************************************************************************/
10161
10162
/** Return the compressed content that can be natively obtained for the
10163
 * window of interest and requested bands.
10164
 *
10165
 * For example, a tiled dataset may be able to return data in compressed format
10166
 * if the window of interest matches exactly a tile. For some formats, drivers
10167
 * may also be example to merge several tiles together (not currently
10168
 * implemented though).
10169
 *
10170
 * The implementation should make sure that the content returned forms a valid
10171
 * standalone file. For example, for the GeoTIFF implementation of this method,
10172
 * when extracting a JPEG tile, the method will automatically adds the content
10173
 * of the JPEG Huffman and/or quantization tables that might be stored in the
10174
 * TIFF JpegTables tag, and not in tile data itself.
10175
 *
10176
 * In the general case this method will return CE_Failure.
10177
 *
10178
 * This is the same as C++ method GDALDataset:ReadCompressedData().
10179
 *
10180
 * @param hDS Dataset handle.
10181
 *
10182
 * @param pszFormat Requested compression format (e.g. "JPEG",
10183
 * "WEBP", "JXL"). This is the MIME type of one of the values
10184
 * returned by GetCompressionFormats(). The format string is designed to
10185
 * potentially include at a later point key=value optional parameters separated
10186
 * by a semi-colon character. At time of writing, none are implemented.
10187
 * ReadCompressedData() implementations should verify optional parameters and
10188
 * return CE_Failure if they cannot support one of them.
10189
 *
10190
 * @param nXOff The pixel offset to the top left corner of the region
10191
 * of the band to be accessed.  This would be zero to start from the left side.
10192
 *
10193
 * @param nYOff The line offset to the top left corner of the region
10194
 * of the band to be accessed.  This would be zero to start from the top.
10195
 *
10196
 * @param nXSize The width of the region of the band to be accessed in pixels.
10197
 *
10198
 * @param nYSize The height of the region of the band to be accessed in lines.
10199
 *
10200
 * @param nBandCount the number of bands being requested.
10201
 *
10202
 * @param panBandList the list of nBandCount band numbers.
10203
 * Note band numbers are 1 based. This may be NULL to select the first
10204
 * nBandCount bands.
10205
 *
10206
 * @param ppBuffer Pointer to a buffer to store the compressed data or nullptr.
10207
 * If ppBuffer is not nullptr, then pnBufferSize should also not be nullptr.
10208
 * If ppBuffer is not nullptr, and *ppBuffer is not nullptr, then the provided
10209
 * buffer will be filled with the compressed data, provided that pnBufferSize
10210
 * and *pnBufferSize are not nullptr, and *pnBufferSize, indicating the size
10211
 * of *ppBuffer, is sufficiently large to hold the data.
10212
 * If ppBuffer is not nullptr, but *ppBuffer is nullptr, then the method will
10213
 * allocate *ppBuffer using VSIMalloc(), and thus the caller is responsible to
10214
 * free it with VSIFree().
10215
 * If ppBuffer is nullptr, then the compressed data itself will not be returned,
10216
 * but *pnBufferSize will be updated with an upper bound of the size that would
10217
 * be necessary to hold it (if pnBufferSize != nullptr).
10218
 *
10219
 * @param pnBufferSize Output buffer size, or nullptr.
10220
 * If ppBuffer != nullptr && *ppBuffer != nullptr, then pnBufferSize should
10221
 * be != nullptr and *pnBufferSize contain the size of *ppBuffer. If the
10222
 * method is successful, *pnBufferSize will be updated with the actual size
10223
 * used.
10224
 *
10225
 * @param ppszDetailedFormat Pointer to an output string, or nullptr.
10226
 * If ppszDetailedFormat is not nullptr, then, on success, the method will
10227
 * allocate a new string in *ppszDetailedFormat (to be freed with VSIFree())
10228
 * *ppszDetailedFormat might contain strings like
10229
 * "JPEG;frame_type=SOF0_baseline;bit_depth=8;num_components=3;"
10230
 * "subsampling=4:2:0;colorspace=YCbCr" or simply the MIME type.
10231
 * The string will contain at least as much information as what
10232
 * GetCompressionFormats() returns, and potentially more when
10233
 * ppBuffer != nullptr.
10234
 *
10235
 * @return CE_None in case of success, CE_Failure otherwise.
10236
 *
10237
 * @since GDAL 3.7
10238
 */
10239
CPLErr GDALDatasetReadCompressedData(GDALDatasetH hDS, const char *pszFormat,
10240
                                     int nXOff, int nYOff, int nXSize,
10241
                                     int nYSize, int nBandCount,
10242
                                     const int *panBandList, void **ppBuffer,
10243
                                     size_t *pnBufferSize,
10244
                                     char **ppszDetailedFormat)
10245
0
{
10246
0
    VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10247
0
    return GDALDataset::FromHandle(hDS)->ReadCompressedData(
10248
0
        pszFormat, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandList,
10249
0
        ppBuffer, pnBufferSize, ppszDetailedFormat);
10250
0
}
10251
10252
/************************************************************************/
10253
/*                           CanBeCloned()                              */
10254
/************************************************************************/
10255
10256
//! @cond Doxygen_Suppress
10257
10258
/** This method is called by GDALThreadSafeDataset::Create() to determine if
10259
 * it is possible to create a thread-safe wrapper for a dataset, which involves
10260
 * the ability to Clone() it.
10261
 *
10262
 * Implementations of this method must be thread-safe.
10263
 *
10264
 * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10265
 *                    expressing the intended use for thread-safety.
10266
 *                    Currently, the only valid scope is in the base
10267
 *                    implementation is GDAL_OF_RASTER.
10268
 * @param bCanShareState Determines if cloned datasets are allowed to share
10269
 *                       state with the dataset they have been cloned from.
10270
 *                       If set to true, the dataset from which they have been
10271
 *                       cloned from must remain opened during the lifetime of
10272
 *                       its clones.
10273
 * @return true if the Clone() method is expected to succeed with the same values
10274
 *         of nScopeFlags and bCanShareState.
10275
 */
10276
bool GDALDataset::CanBeCloned(int nScopeFlags,
10277
                              [[maybe_unused]] bool bCanShareState) const
10278
0
{
10279
0
    return m_bCanBeReopened && nScopeFlags == GDAL_OF_RASTER;
10280
0
}
10281
10282
//! @endcond
10283
10284
/************************************************************************/
10285
/*                               Clone()                                */
10286
/************************************************************************/
10287
10288
//! @cond Doxygen_Suppress
10289
10290
/** This method "clones" the current dataset, that is it returns a new instance
10291
 * that is opened on the same underlying "file".
10292
 *
10293
 * The base implementation uses GDALDataset::Open() to re-open the dataset.
10294
 * The MEM driver has a specialized implementation that returns a new instance,
10295
 * but which shares the same memory buffer as this.
10296
 *
10297
 * Implementations of this method must be thread-safe.
10298
 *
10299
 * @param nScopeFlags Combination of GDAL_OF_RASTER, GDAL_OF_VECTOR, etc. flags,
10300
 *                    expressing the intended use for thread-safety.
10301
 *                    Currently, the only valid scope is in the base
10302
 *                    implementation is GDAL_OF_RASTER.
10303
 * @param bCanShareState Determines if cloned datasets are allowed to share
10304
 *                       state with the dataset they have been cloned from.
10305
 *                       If set to true, the dataset from which they have been
10306
 *                       cloned from must remain opened during the lifetime of
10307
 *                       its clones.
10308
 * @return a new instance, or nullptr in case of error.
10309
 */
10310
std::unique_ptr<GDALDataset>
10311
GDALDataset::Clone(int nScopeFlags, [[maybe_unused]] bool bCanShareState) const
10312
0
{
10313
0
    CPLStringList aosAllowedDrivers;
10314
0
    if (poDriver)
10315
0
        aosAllowedDrivers.AddString(poDriver->GetDescription());
10316
0
    return std::unique_ptr<GDALDataset>(GDALDataset::Open(
10317
0
        GetDescription(),
10318
0
        nScopeFlags | GDAL_OF_INTERNAL | GDAL_OF_VERBOSE_ERROR,
10319
0
        aosAllowedDrivers.List(), papszOpenOptions));
10320
0
}
10321
10322
//! @endcond
10323
10324
/************************************************************************/
10325
/*                    GeolocationToPixelLine()                          */
10326
/************************************************************************/
10327
10328
/** Transform georeferenced coordinates to pixel/line coordinates.
10329
 *
10330
 * When poSRS is null, those georeferenced coordinates (dfGeolocX, dfGeolocY)
10331
 * must be in the "natural" SRS of the dataset, that is the one returned by
10332
 * GetSpatialRef() if there is a geotransform, GetGCPSpatialRef() if there are
10333
 * GCPs, WGS 84 if there are RPC coefficients, or the SRS of the geolocation
10334
 * array (generally WGS 84) if there is a geolocation array.
10335
 * If that natural SRS is a geographic one, dfGeolocX must be a longitude, and
10336
 * dfGeolocY a latitude. If that natural SRS is a projected one, dfGeolocX must
10337
 * be a easting, and dfGeolocY a northing.
10338
 *
10339
 * When poSRS is set to a non-null value, (dfGeolocX, dfGeolocY) must be
10340
 * expressed in that CRS, and that tuple must be conformant with the
10341
 * data-axis-to-crs-axis setting of poSRS, that is the one returned by
10342
 * the OGRSpatialReference::GetDataAxisToSRSAxisMapping(). If you want to be sure
10343
 * of the axis order, then make sure to call poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)
10344
 * before calling this method, and in that case, dfGeolocX must be a longitude
10345
 * or an easting value, and dfGeolocX a latitude or a northing value.
10346
 *
10347
 * This method uses GDALCreateGenImgProjTransformer2() underneath.
10348
 *
10349
 * @param dfGeolocX X coordinate of the position (longitude or easting if poSRS
10350
 * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10351
 * where interpolation should be done.
10352
 * @param dfGeolocY Y coordinate of the position (latitude or northing if poSRS
10353
 * is null, otherwise consistent with poSRS data-axis-to-crs-axis mapping),
10354
 * where interpolation should be done.
10355
 * @param poSRS If set, override the natural CRS in which dfGeolocX, dfGeolocY are expressed
10356
 * @param[out] pdfPixel Pointer to the variable where to the store the pixel/column coordinate.
10357
 * @param[out] pdfLine Pointer to the variable where to the store the line coordinate.
10358
 * @param papszTransformerOptions Options accepted by GDALCreateGenImgProjTransformer2(), or nullptr.
10359
 *
10360
 * @return CE_None on success, or an error code on failure.
10361
 * @since GDAL 3.11
10362
 */
10363
10364
CPLErr
10365
GDALDataset::GeolocationToPixelLine(double dfGeolocX, double dfGeolocY,
10366
                                    const OGRSpatialReference *poSRS,
10367
                                    double *pdfPixel, double *pdfLine,
10368
                                    CSLConstList papszTransformerOptions) const
10369
0
{
10370
0
    CPLStringList aosTO(papszTransformerOptions);
10371
10372
0
    if (poSRS)
10373
0
    {
10374
0
        const char *const apszOptions[] = {"FORMAT=WKT2", nullptr};
10375
0
        const std::string osWKT = poSRS->exportToWkt(apszOptions);
10376
0
        aosTO.SetNameValue("DST_SRS", osWKT.c_str());
10377
0
        const auto eAxisMappingStrategy = poSRS->GetAxisMappingStrategy();
10378
0
        if (eAxisMappingStrategy == OAMS_TRADITIONAL_GIS_ORDER)
10379
0
            aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10380
0
                               "TRADITIONAL_GIS_ORDER");
10381
0
        else if (eAxisMappingStrategy == OAMS_AUTHORITY_COMPLIANT)
10382
0
            aosTO.SetNameValue("DST_SRS_AXIS_MAPPING_STRATEGY",
10383
0
                               "AUTHORITY_COMPLIANT");
10384
0
        else
10385
0
        {
10386
0
            const auto &anValues = poSRS->GetDataAxisToSRSAxisMapping();
10387
0
            std::string osVal;
10388
0
            for (int v : anValues)
10389
0
            {
10390
0
                if (!osVal.empty())
10391
0
                    osVal += ',';
10392
0
                osVal += std::to_string(v);
10393
0
            }
10394
0
            aosTO.SetNameValue("DST_SRS_DATA_AXIS_TO_SRS_AXIS_MAPPING",
10395
0
                               osVal.c_str());
10396
0
        }
10397
0
    }
10398
10399
0
    auto hTransformer = GDALCreateGenImgProjTransformer2(
10400
0
        GDALDataset::ToHandle(const_cast<GDALDataset *>(this)), nullptr,
10401
0
        aosTO.List());
10402
0
    if (hTransformer == nullptr)
10403
0
    {
10404
0
        return CE_Failure;
10405
0
    }
10406
10407
0
    double z = 0;
10408
0
    int bSuccess = 0;
10409
0
    GDALGenImgProjTransform(hTransformer, TRUE, 1, &dfGeolocX, &dfGeolocY, &z,
10410
0
                            &bSuccess);
10411
0
    GDALDestroyTransformer(hTransformer);
10412
0
    if (bSuccess)
10413
0
    {
10414
0
        if (pdfPixel)
10415
0
            *pdfPixel = dfGeolocX;
10416
0
        if (pdfLine)
10417
0
            *pdfLine = dfGeolocY;
10418
0
        return CE_None;
10419
0
    }
10420
0
    else
10421
0
    {
10422
0
        return CE_Failure;
10423
0
    }
10424
0
}
10425
10426
/************************************************************************/
10427
/*                  GDALDatasetGeolocationToPixelLine()                 */
10428
/************************************************************************/
10429
10430
/** Transform georeferenced coordinates to pixel/line coordinates.
10431
 *
10432
 * @see GDALDataset::GeolocationToPixelLine()
10433
 * @since GDAL 3.11
10434
 */
10435
10436
CPLErr GDALDatasetGeolocationToPixelLine(GDALDatasetH hDS, double dfGeolocX,
10437
                                         double dfGeolocY,
10438
                                         OGRSpatialReferenceH hSRS,
10439
                                         double *pdfPixel, double *pdfLine,
10440
                                         CSLConstList papszTransformerOptions)
10441
0
{
10442
0
    VALIDATE_POINTER1(hDS, "GDALDatasetGeolocationToPixelLine", CE_Failure);
10443
10444
0
    GDALDataset *poDS = GDALDataset::FromHandle(hDS);
10445
0
    return poDS->GeolocationToPixelLine(
10446
0
        dfGeolocX, dfGeolocY, OGRSpatialReference::FromHandle(hSRS), pdfPixel,
10447
0
        pdfLine, papszTransformerOptions);
10448
0
}
10449
10450
/************************************************************************/
10451
/*                               GetExtent()                            */
10452
/************************************************************************/
10453
10454
/** Return extent of dataset in specified CRS.
10455
 *
10456
 * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10457
 *
10458
 * For rasters, the base implementation of this method only succeeds if
10459
 * GetGeoTransform() and GetSpatialRef() succeed.
10460
 * For vectors, the base implementation of this method iterates over layers
10461
 * and call their OGRLayer::GetExtent() method.
10462
 *
10463
 * TestCapability(GDsCFastGetExtent) can be used to test if the execution
10464
 * time of this method is fast.
10465
 *
10466
 * This is the same as C function GDALGetExtent()
10467
 *
10468
 * @param[out] psExtent Pointer to output extent. Must NOT be null.
10469
 * @param poCRS CRS in which to express the extent. If not specified, this will
10470
 * be the raster CRS or the CRS of the first layer for a vector dataset.
10471
 * @return CE_None in case of success, CE_Failure otherwise
10472
 * @since GDAL 3.12
10473
 */
10474
10475
CPLErr GDALDataset::GetExtent(OGREnvelope *psExtent,
10476
                              const OGRSpatialReference *poCRS) const
10477
0
{
10478
0
    auto poThisDS = const_cast<GDALDataset *>(this);
10479
0
    const OGRSpatialReference *poThisCRS = poThisDS->GetSpatialRef();
10480
0
    int nLayerCount = 0;
10481
0
    if (!poThisCRS)
10482
0
    {
10483
0
        nLayerCount = poThisDS->GetLayerCount();
10484
0
        if (nLayerCount >= 1)
10485
0
        {
10486
0
            if (auto poLayer = poThisDS->GetLayer(0))
10487
0
                poThisCRS = poLayer->GetSpatialRef();
10488
0
        }
10489
0
        if (!poThisCRS)
10490
0
            return CE_Failure;
10491
0
    }
10492
0
    if (!poCRS)
10493
0
        poCRS = poThisCRS;
10494
10495
0
    *psExtent = OGREnvelope();
10496
10497
0
    std::array<double, 6> adfGT;
10498
0
    const bool bHasGT = poThisDS->GetGeoTransform(adfGT.data()) == CE_None;
10499
0
    if (bHasGT)
10500
0
    {
10501
0
        auto poCT = std::unique_ptr<OGRCoordinateTransformation>(
10502
0
            OGRCreateCoordinateTransformation(poThisCRS, poCRS));
10503
0
        if (poCT)
10504
0
        {
10505
0
            constexpr int DENSIFY_POINT_COUNT = 21;
10506
0
            OGREnvelope sEnvTmp;
10507
0
            double dfULX = adfGT[0];
10508
0
            double dfULY = adfGT[3];
10509
0
            double dfURX = 0, dfURY = 0;
10510
0
            GDALApplyGeoTransform(adfGT.data(), nRasterXSize, 0, &dfURX,
10511
0
                                  &dfURY);
10512
0
            double dfLLX = 0, dfLLY = 0;
10513
0
            GDALApplyGeoTransform(adfGT.data(), 0, nRasterYSize, &dfLLX,
10514
0
                                  &dfLLY);
10515
0
            double dfLRX = 0, dfLRY = 0;
10516
0
            GDALApplyGeoTransform(adfGT.data(), nRasterXSize, nRasterYSize,
10517
0
                                  &dfLRX, &dfLRY);
10518
0
            const double xmin =
10519
0
                std::min(std::min(dfULX, dfURX), std::min(dfLLX, dfLRX));
10520
0
            const double ymin =
10521
0
                std::min(std::min(dfULY, dfURY), std::min(dfLLY, dfLRY));
10522
0
            const double xmax =
10523
0
                std::max(std::max(dfULX, dfURX), std::max(dfLLX, dfLRX));
10524
0
            const double ymax =
10525
0
                std::max(std::max(dfULY, dfURY), std::max(dfLLY, dfLRY));
10526
0
            if (poCT->TransformBounds(xmin, ymin, xmax, ymax, &(sEnvTmp.MinX),
10527
0
                                      &(sEnvTmp.MinY), &(sEnvTmp.MaxX),
10528
0
                                      &(sEnvTmp.MaxY), DENSIFY_POINT_COUNT))
10529
0
            {
10530
0
                *psExtent = std::move(sEnvTmp);
10531
0
            }
10532
0
        }
10533
0
    }
10534
10535
0
    if (nLayerCount > 0)
10536
0
    {
10537
0
        for (auto &&poLayer : poThisDS->GetLayers())
10538
0
        {
10539
0
            auto poLayerCRS = poLayer->GetSpatialRef();
10540
0
            if (poLayerCRS)
10541
0
            {
10542
0
                OGREnvelope sLayerExtent;
10543
0
                if (poLayer->GetExtent(&sLayerExtent) == OGRERR_NONE)
10544
0
                {
10545
0
                    auto poCT = std::unique_ptr<OGRCoordinateTransformation>(
10546
0
                        OGRCreateCoordinateTransformation(poLayerCRS, poCRS));
10547
0
                    if (poCT)
10548
0
                    {
10549
0
                        constexpr int DENSIFY_POINT_COUNT = 21;
10550
0
                        OGREnvelope sEnvTmp;
10551
0
                        if (poCT->TransformBounds(
10552
0
                                sLayerExtent.MinX, sLayerExtent.MinY,
10553
0
                                sLayerExtent.MaxX, sLayerExtent.MaxY,
10554
0
                                &(sEnvTmp.MinX), &(sEnvTmp.MinY),
10555
0
                                &(sEnvTmp.MaxX), &(sEnvTmp.MaxY),
10556
0
                                DENSIFY_POINT_COUNT))
10557
0
                        {
10558
0
                            psExtent->Merge(sEnvTmp);
10559
0
                        }
10560
0
                    }
10561
0
                }
10562
0
            }
10563
0
        }
10564
0
    }
10565
10566
0
    return psExtent->IsInit() ? CE_None : CE_Failure;
10567
0
}
10568
10569
/************************************************************************/
10570
/*                           GDALGetExtent()                            */
10571
/************************************************************************/
10572
10573
/** Return extent of dataset in specified CRS.
10574
 *
10575
 * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10576
 *
10577
 * For rasters, the base implementation of this method only succeeds if
10578
 * GetGeoTransform() and GetSpatialRef() succeed.
10579
 * For vectors, the base implementation of this method iterates over layers
10580
 * and call their OGRLayer::GetExtent() method.
10581
 *
10582
 * TestCapability(GDsCFastGetExtent) can be used to test if the execution
10583
 * time of this method is fast.
10584
 *
10585
 * This is the same as C++ method GDALDataset::GetExtent()
10586
 *
10587
 * @param hDS Dataset handle. Must NOT be null.
10588
 * @param[out] psExtent Pointer to output extent. Must NOT be null.
10589
 * @param hCRS CRS in which to express the extent. If not specified, this will
10590
 * be the raster CRS or the CRS of the first layer for a vector dataset.
10591
 * @return extent in poCRS (valid only if IsInit() method returns true)
10592
 * @since GDAL 3.12
10593
 */
10594
10595
CPLErr GDALGetExtent(GDALDatasetH hDS, OGREnvelope *psExtent,
10596
                     OGRSpatialReferenceH hCRS)
10597
0
{
10598
0
    VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10599
0
    VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
10600
0
    return GDALDataset::FromHandle(hDS)->GetExtent(
10601
0
        psExtent, OGRSpatialReference::FromHandle(hCRS));
10602
0
}
10603
10604
/************************************************************************/
10605
/*                         GetExtentWGS84LongLat()                      */
10606
/************************************************************************/
10607
10608
/** Return extent of dataset in WGS84 longitude/latitude
10609
 *
10610
 * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10611
 *
10612
 * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
10613
 * time of this method is fast.
10614
 *
10615
 * This is the same as C function GDALGetExtentWGS84LongLat()
10616
 *
10617
 * @return extent (valid only if IsInit() method returns true)
10618
 * @since GDAL 3.12
10619
 */
10620
10621
CPLErr GDALDataset::GetExtentWGS84LongLat(OGREnvelope *psExtent) const
10622
0
{
10623
0
    OGRSpatialReference oSRS_WGS84;
10624
0
    oSRS_WGS84.SetFromUserInput("WGS84");
10625
0
    oSRS_WGS84.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
10626
0
    return GetExtent(psExtent, &oSRS_WGS84);
10627
0
}
10628
10629
/************************************************************************/
10630
/*                    GDALGetExtentWGS84LongLat()                       */
10631
/************************************************************************/
10632
10633
/** Return extent of dataset in WGS84 longitude/latitude
10634
 *
10635
 * OGREnvelope.MinX/MaxX represents longitudes, and MinY/MaxY latitudes.
10636
 *
10637
 * TestCapability(GDsCFastGetExtentWGS84LongLat) can be used to test if the execution
10638
 * time of this method is fast.
10639
 *
10640
 * This is the same as C++ method GDALDataset::GetExtentWGS84LongLat()
10641
 *
10642
 * @param hDS Dataset handle. Must NOT be null.
10643
 * @param[out] psExtent Pointer to output extent. Must NOT be null.
10644
 * @return extent (valid only if IsInit() method returns true)
10645
 * @since GDAL 3.12
10646
 */
10647
10648
CPLErr GDALGetExtentWGS84LongLat(GDALDatasetH hDS, OGREnvelope *psExtent)
10649
0
{
10650
0
    VALIDATE_POINTER1(hDS, __func__, CE_Failure);
10651
0
    VALIDATE_POINTER1(psExtent, __func__, CE_Failure);
10652
0
    return GDALDataset::FromHandle(hDS)->GetExtentWGS84LongLat(psExtent);
10653
0
}
10654
10655
/************************************************************************/
10656
/*                  ReportUpdateNotSupportedByDriver()                  */
10657
/************************************************************************/
10658
10659
//! @cond Doxygen_Suppress
10660
10661
/* static */
10662
void GDALDataset::ReportUpdateNotSupportedByDriver(const char *pszDriverName)
10663
0
{
10664
0
    CPLError(CE_Failure, CPLE_NotSupported,
10665
0
             "The %s driver does not support update access to existing "
10666
0
             "datasets.",
10667
0
             pszDriverName);
10668
0
}
10669
10670
//! @endcond
10671
10672
/************************************************************************/
10673
/*                         BuildFilename()                              */
10674
/************************************************************************/
10675
10676
/** Generates a filename, potentially relative to another one.
10677
 *
10678
 * Given the path to a reference directory, and a path to a file
10679
 * referenced from it, build a path to the file that the current application
10680
 * can use. If the file path is already absolute, rather than relative, or if
10681
 * bRelativeToReferencePath is false, then the filename of interest will be
10682
 * returned unaltered.
10683
 *
10684
 * This is enhanced version of CPLProjectRelativeFilenameSafe() that takes
10685
 * into account the subdataset syntax.
10686
 *
10687
 * Examples:
10688
 * \code{.cpp}
10689
 * BuildFilename("tmp/abc.gif", "abc/def", true) == "abc/def/tmp/abc.gif"
10690
 * BuildFilename("../abc.gif", "/abc/def") == "/abc/abc.gif"
10691
 * BuildFilename("abc.gif", "C:\WIN", true) == "C:\WIN\abc.gif"
10692
 * BuildFilename("abc.gif", "C:\WIN", false) == "abc.gif"
10693
 * BuildFilename("/home/even/foo.tif", "/home/even/workdir", true) == "/home/even/foo.tif"
10694
 * \endcode
10695
 *
10696
 * @param pszFilename Filename of interest.
10697
 * @param pszReferencePath Path to a reference directory.
10698
 * @param bRelativeToReferencePath Whether pszFilename, if a relative path, is
10699
 *                                 relative to pszReferencePath
10700
 * @since 3.11
10701
 */
10702
10703
/* static */
10704
std::string GDALDataset::BuildFilename(const char *pszFilename,
10705
                                       const char *pszReferencePath,
10706
                                       bool bRelativeToReferencePath)
10707
0
{
10708
0
    std::string osSrcDSName;
10709
0
    if (pszReferencePath != nullptr && bRelativeToReferencePath)
10710
0
    {
10711
        // Try subdatasetinfo API first
10712
        // Note: this will become the only branch when subdatasetinfo will become
10713
        //       available for NITF_IM, RASTERLITE and TILEDB
10714
0
        const auto oSubDSInfo{GDALGetSubdatasetInfo(pszFilename)};
10715
0
        if (oSubDSInfo && !oSubDSInfo->GetPathComponent().empty())
10716
0
        {
10717
0
            auto path{oSubDSInfo->GetPathComponent()};
10718
0
            osSrcDSName = oSubDSInfo->ModifyPathComponent(
10719
0
                CPLProjectRelativeFilenameSafe(pszReferencePath, path.c_str())
10720
0
                    .c_str());
10721
0
            GDALDestroySubdatasetInfo(oSubDSInfo);
10722
0
        }
10723
0
        else
10724
0
        {
10725
0
            bool bDone = false;
10726
0
            for (const char *pszSyntax : apszSpecialSubDatasetSyntax)
10727
0
            {
10728
0
                CPLString osPrefix(pszSyntax);
10729
0
                osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
10730
0
                if (pszSyntax[osPrefix.size()] == '"')
10731
0
                    osPrefix += '"';
10732
0
                if (EQUALN(pszFilename, osPrefix, osPrefix.size()))
10733
0
                {
10734
0
                    if (STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}"))
10735
0
                    {
10736
0
                        const char *pszLastPart = strrchr(pszFilename, ':') + 1;
10737
                        // CSV:z:/foo.xyz
10738
0
                        if ((pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
10739
0
                            pszLastPart - pszFilename >= 3 &&
10740
0
                            pszLastPart[-3] == ':')
10741
0
                        {
10742
0
                            pszLastPart -= 2;
10743
0
                        }
10744
0
                        CPLString osPrefixFilename = pszFilename;
10745
0
                        osPrefixFilename.resize(pszLastPart - pszFilename);
10746
0
                        osSrcDSName = osPrefixFilename +
10747
0
                                      CPLProjectRelativeFilenameSafe(
10748
0
                                          pszReferencePath, pszLastPart);
10749
0
                        bDone = true;
10750
0
                    }
10751
0
                    else if (STARTS_WITH_CI(pszSyntax + osPrefix.size(),
10752
0
                                            "{FILENAME}"))
10753
0
                    {
10754
0
                        CPLString osFilename(pszFilename + osPrefix.size());
10755
0
                        size_t nPos = 0;
10756
0
                        if (osFilename.size() >= 3 && osFilename[1] == ':' &&
10757
0
                            (osFilename[2] == '\\' || osFilename[2] == '/'))
10758
0
                            nPos = 2;
10759
0
                        nPos = osFilename.find(
10760
0
                            pszSyntax[osPrefix.size() + strlen("{FILENAME}")],
10761
0
                            nPos);
10762
0
                        if (nPos != std::string::npos)
10763
0
                        {
10764
0
                            const CPLString osSuffix = osFilename.substr(nPos);
10765
0
                            osFilename.resize(nPos);
10766
0
                            osSrcDSName = osPrefix +
10767
0
                                          CPLProjectRelativeFilenameSafe(
10768
0
                                              pszReferencePath, osFilename) +
10769
0
                                          osSuffix;
10770
0
                            bDone = true;
10771
0
                        }
10772
0
                    }
10773
0
                    break;
10774
0
                }
10775
0
            }
10776
0
            if (!bDone)
10777
0
            {
10778
0
                std::string osReferencePath = pszReferencePath;
10779
0
                if (!CPLIsFilenameRelative(pszReferencePath))
10780
0
                {
10781
                    // Simplify path by replacing "foo/a/../b" with "foo/b"
10782
0
                    while (STARTS_WITH(pszFilename, "../"))
10783
0
                    {
10784
0
                        osReferencePath =
10785
0
                            CPLGetPathSafe(osReferencePath.c_str());
10786
0
                        pszFilename += strlen("../");
10787
0
                    }
10788
0
                }
10789
10790
0
                osSrcDSName = CPLProjectRelativeFilenameSafe(
10791
0
                    osReferencePath.c_str(), pszFilename);
10792
0
            }
10793
0
        }
10794
0
    }
10795
0
    else
10796
0
    {
10797
0
        osSrcDSName = pszFilename;
10798
0
    }
10799
0
    return osSrcDSName;
10800
0
}