Coverage Report

Created: 2026-09-26 08:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitebase.h
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Definition of classes and functions used by SQLite and GPKG drivers
5
 * Author:   Even Rouault <even dot rouault at spatialys.com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2021, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#ifndef OGR_SQLITE_BASE_H_INCLUDED
14
#define OGR_SQLITE_BASE_H_INCLUDED
15
16
#include "cpl_vsi.h"
17
#include "cpl_string.h"
18
#include "gdal_pam.h"
19
#include "ogrsf_frmts.h"
20
21
#include <sqlite3.h>
22
23
// to avoid -Wold-style-cast with some compilers
24
#undef SQLITE_TRANSIENT
25
343k
#define SQLITE_TRANSIENT reinterpret_cast<sqlite3_destructor_type>(-1)
26
27
#include <map>
28
#include <utility>
29
#include <vector>
30
31
/************************************************************************/
32
/*         Format used to store geometry data in the database.          */
33
/************************************************************************/
34
35
enum OGRSQLiteGeomFormat
36
{
37
    OSGF_WKT,
38
    OSGF_WKB,
39
    OSGF_FGF,
40
    OSGF_SpatiaLite,
41
    OSGF_Unknown,
42
};
43
44
/************************************************************************/
45
/*                        OGRSQLiteGeomFieldDefn                        */
46
/************************************************************************/
47
48
class OGRSQLiteGeomFieldDefn final : public OGRGeomFieldDefn
49
{
50
  public:
51
    OGRSQLiteGeomFieldDefn(const char *pszNameIn, int iGeomColIn)
52
4.82k
        : OGRGeomFieldDefn(pszNameIn, wkbUnknown), m_iCol(iGeomColIn)
53
4.82k
    {
54
4.82k
    }
55
56
    ~OGRSQLiteGeomFieldDefn() override;
57
58
    int m_nSRSId = -1;
59
    int m_iCol; /* ordinal of geometry field in SQL statement */
60
    bool m_bTriedAsSpatiaLite = false;
61
    OGRSQLiteGeomFormat m_eGeomFormat = OSGF_Unknown;
62
    OGREnvelope m_oCachedExtent{};
63
    bool m_bCachedExtentIsValid = false;
64
    bool m_bHasSpatialIndex = false;
65
    bool m_bHasCheckedSpatialIndexTable = false;
66
    std::vector<std::pair<CPLString, CPLString>> m_aosDisabledTriggers{};
67
};
68
69
/************************************************************************/
70
/*                         OGRSQLiteFeatureDefn                         */
71
/************************************************************************/
72
73
class OGRSQLiteFeatureDefn final : public OGRFeatureDefn
74
{
75
  public:
76
    explicit OGRSQLiteFeatureDefn(const char *pszName = nullptr)
77
72.0k
        : OGRFeatureDefn(pszName)
78
72.0k
    {
79
72.0k
        SetGeomType(wkbNone);
80
72.0k
    }
81
82
    ~OGRSQLiteFeatureDefn() override;
83
84
    OGRSQLiteGeomFieldDefn *myGetGeomFieldDefn(int i)
85
1.07M
    {
86
1.07M
        return cpl::down_cast<OGRSQLiteGeomFieldDefn *>(GetGeomFieldDefn(i));
87
1.07M
    }
88
89
    const OGRSQLiteGeomFieldDefn *myGetGeomFieldDefn(int i) const
90
0
    {
91
0
        return cpl::down_cast<const OGRSQLiteGeomFieldDefn *>(
92
0
            GetGeomFieldDefn(i));
93
0
    }
94
};
95
96
/************************************************************************/
97
/*                      IOGRSQLiteGetSpatialWhere                       */
98
/************************************************************************/
99
100
class IOGRSQLiteGetSpatialWhere /* non final */
101
{
102
  public:
103
    virtual ~IOGRSQLiteGetSpatialWhere();
104
105
    virtual bool HasFastSpatialFilter(int iGeomCol) = 0;
106
    virtual CPLString GetSpatialWhere(int iGeomCol,
107
                                      OGRGeometry *poFilterGeom) = 0;
108
};
109
110
/************************************************************************/
111
/*                       OGRSQLiteBaseDataSource                        */
112
/************************************************************************/
113
114
/* Used by both OGRSQLiteDataSource and OGRGeoPackageDataSource */
115
class OGRSQLiteBaseDataSource CPL_NON_FINAL : public GDALPamDataset
116
{
117
  protected:
118
    char *m_pszFilename = nullptr;
119
    std::string
120
        m_osFilenameForSQLiteOpen{};  // generally m_pszFilename, but can be
121
                                      // also file:{m_pszFilename}?nolock=1
122
    bool m_bNoLock = false;
123
    std::string
124
        m_osFinalFilename{};  // use when generating a network hosted file with
125
                              // CPL_VSIL_USE_TEMP_FILE_FOR_RANDOM_WRITE=YES
126
    bool m_bCallUndeclareFileNotToOpen = false;
127
128
    sqlite3 *hDB = nullptr;
129
130
    sqlite3_vfs *pMyVFS = nullptr;
131
132
    VSILFILE *fpMainFile =
133
        nullptr; /* Set by the VFS layer when it opens the DB */
134
                 /* Must *NOT* be closed by the datasource explicitly. */
135
136
    bool OpenOrCreateDB(int flags, bool bRegisterOGR2SQLiteExtensions,
137
                        bool bLoadExtensions);
138
    bool SetSynchronous();
139
    bool SetCacheSize();
140
    void LoadExtensions();
141
142
    bool CloseDB();
143
144
    std::map<CPLString, OGREnvelope> oMapSQLEnvelope{};
145
146
    mutable bool m_bHasPopulatedRelationships = false;
147
    mutable std::map<std::string, std::unique_ptr<GDALRelationship>>
148
        m_osMapRelationships{};
149
150
    void *hSpatialiteCtxt = nullptr;
151
    bool InitSpatialite();
152
    void FinishSpatialite();
153
154
    int m_bUserTransactionActive = FALSE;
155
    int m_nSoftTransactionLevel = 0;
156
    std::vector<std::string> m_aosSavepoints{};
157
    // The transaction was implicitly started by SAVEPOINT
158
    bool m_bImplicitTransactionOpened = false;
159
160
    OGRErr DoTransactionCommand(const char *pszCommand);
161
162
    bool DealWithOgrSchemaOpenOption(CSLConstList papszOpenOptionsIn);
163
164
    CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteBaseDataSource)
165
166
  public:
167
    OGRSQLiteBaseDataSource();
168
    ~OGRSQLiteBaseDataSource() override;
169
170
    std::string GetCurrentSavepoint() const
171
66.2k
    {
172
66.2k
        return m_aosSavepoints.empty() ? "" : m_aosSavepoints.back();
173
66.2k
    }
174
175
    std::string GetFirstSavepoint() const
176
0
    {
177
0
        return m_aosSavepoints.empty() ? "" : m_aosSavepoints.front();
178
0
    }
179
180
    bool IsInTransaction() const;
181
182
    sqlite3 *GetDB()
183
2.09M
    {
184
2.09M
        return hDB;
185
2.09M
    }
186
187
    sqlite3_vfs *GetVFS()
188
0
    {
189
0
        return pMyVFS;
190
0
    }
191
192
    inline bool GetUpdate() const
193
1.76M
    {
194
1.76M
        return eAccess == GA_Update;
195
1.76M
    }
196
197
    VSILFILE *GetVSILFILE() const
198
0
    {
199
0
        return fpMainFile;
200
0
    }
201
202
    void NotifyFileOpened(const char *pszFilename, VSILFILE *fp);
203
204
    const OGREnvelope *GetEnvelopeFromSQL(const CPLString &osSQL);
205
    void SetEnvelopeForSQL(const CPLString &osSQL,
206
                           const OGREnvelope &oEnvelope);
207
208
    virtual std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
209
    GetLayerWithGetSpatialWhereByName(const char *pszName) = 0;
210
211
    OGRErr AbortSQL() override;
212
    bool SetQueryLoggerFunc(GDALQueryLoggerFunc pfnQueryLoggerFuncIn,
213
                            void *poQueryLoggerArgIn) override;
214
215
    OGRErr StartTransaction(int bForce = FALSE) override;
216
    OGRErr CommitTransaction() override;
217
    OGRErr RollbackTransaction() override;
218
219
    bool TestCapability(const char *) const override;
220
221
    void *GetInternalHandle(const char *) override;
222
223
    OGRErr SoftStartTransaction();
224
    OGRErr SoftCommitTransaction();
225
    OGRErr SoftRollbackTransaction();
226
    OGRErr StartSavepoint(const std::string &osName);
227
    OGRErr ReleaseSavepoint(const std::string &osName);
228
    OGRErr RollbackToSavepoint(const std::string &osName);
229
230
    /**
231
     *  Execute a SQL transaction command (BEGIN, COMMIT, ROLLBACK, SAVEPOINT)
232
     *  @return TRUE if the osSQLCommand was recognized as a transaction command
233
     */
234
    bool ProcessTransactionSQL(const std::string &osSQLCommand);
235
236
    OGRErr PragmaCheck(const char *pszPragma, const char *pszExpected,
237
                       int nRowsExpected);
238
239
    virtual void LoadRelationships() const;
240
    void LoadRelationshipsFromForeignKeys(
241
        const std::vector<std::string> &excludedTables) const;
242
    std::vector<std::string>
243
    GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
244
    const GDALRelationship *
245
    GetRelationship(const std::string &name) const override;
246
247
    bool IsSpatialiteLoaded();
248
249
    static int MakeSpatialiteVersionNumber(int x, int y, int z)
250
12.5k
    {
251
12.5k
        return x * 10000 + y * 100 + z;
252
12.5k
    }
253
254
    int GetSpatialiteVersionNumber();
255
256
    bool SpatialiteRequiresTrustedSchemaOn();
257
    bool AreSpatialiteTriggersSafe();
258
259
    // sqlite3_prepare_v2 error logging wrapper
260
    sqlite3_stmt *
261
    prepareSql(sqlite3 *db,      /* Database handle */
262
               const char *zSql, /* SQL statement, UTF-8 encoded */
263
               int nByte = -1    /* Maximum length of zSql in bytes. */
264
    );
265
266
    GDALQueryLoggerFunc pfnQueryLoggerFunc = nullptr;
267
    void *poQueryLoggerArg = nullptr;
268
};
269
270
/************************************************************************/
271
/*                        IOGRSQLiteSelectLayer                         */
272
/************************************************************************/
273
274
class IOGRSQLiteSelectLayer /* non final */
275
{
276
  public:
277
    virtual ~IOGRSQLiteSelectLayer();
278
279
    virtual char *&GetAttrQueryString() = 0;
280
    virtual OGRFeatureQuery *&GetFeatureQuery() = 0;
281
    virtual OGRGeometry *&GetFilterGeom() = 0;
282
    virtual int &GetIGeomFieldFilter() = 0;
283
    virtual const OGRSpatialReference *GetSpatialRef() const = 0;
284
    virtual const OGRFeatureDefn *GetLayerDefn() const = 0;
285
    virtual int InstallFilter(const OGRGeometry *) = 0;
286
    virtual int HasReadFeature() = 0;
287
    virtual void BaseResetReading() = 0;
288
    virtual OGRFeature *BaseGetNextFeature() = 0;
289
    virtual OGRErr BaseSetAttributeFilter(const char *pszQuery) = 0;
290
    virtual GIntBig BaseGetFeatureCount(int bForce) = 0;
291
    virtual bool BaseTestCapability(const char *) const = 0;
292
    virtual OGRErr BaseGetExtent(int iGeomField, OGREnvelope *psExtent,
293
                                 bool bForce) = 0;
294
    virtual bool ValidateGeometryFieldIndexForSetSpatialFilter(
295
        int iGeomField, const OGRGeometry *poGeomIn, bool bIsSelectLayer) = 0;
296
};
297
298
/************************************************************************/
299
/*                 OGRSQLiteSelectLayerCommonBehaviour                  */
300
/************************************************************************/
301
302
class OGRSQLiteSelectLayerCommonBehaviour final
303
{
304
    OGRSQLiteBaseDataSource *m_poDS = nullptr;
305
    IOGRSQLiteSelectLayer *m_poLayer = nullptr;
306
307
    CPLString m_osSQLBase{};
308
309
    bool m_bEmptyLayer = false;
310
    bool m_bAllowResetReadingEvenIfIndexAtZero = false;
311
    bool m_bSpatialFilterInSQL = true;
312
313
    std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
314
    GetBaseLayer(size_t &i) const;
315
    int BuildSQL();
316
317
    CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteSelectLayerCommonBehaviour)
318
319
  public:
320
    CPLString m_osSQLCurrent{};
321
322
    OGRSQLiteSelectLayerCommonBehaviour(OGRSQLiteBaseDataSource *poDS,
323
                                        IOGRSQLiteSelectLayer *poBaseLayer,
324
                                        const CPLString &osSQL,
325
                                        bool bEmptyLayer);
326
327
    void ResetReading();
328
    OGRFeature *GetNextFeature();
329
    GIntBig GetFeatureCount(int);
330
    OGRErr SetSpatialFilter(int iGeomField, const OGRGeometry *);
331
    OGRErr SetAttributeFilter(const char *);
332
    bool TestCapability(const char *) const;
333
    OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent, bool bForce);
334
};
335
336
/************************************************************************/
337
/*                     OGRSQLiteSingleFeatureLayer                      */
338
/************************************************************************/
339
340
class OGRSQLiteSingleFeatureLayer final : public OGRLayer
341
{
342
  private:
343
    int nVal;
344
    char *pszVal;
345
    OGRFeatureDefn *poFeatureDefn;
346
    int iNextShapeId;
347
348
    CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteSingleFeatureLayer)
349
350
  public:
351
    OGRSQLiteSingleFeatureLayer(const char *pszLayerName, int nVal);
352
    OGRSQLiteSingleFeatureLayer(const char *pszLayerName, const char *pszVal);
353
    ~OGRSQLiteSingleFeatureLayer() override;
354
355
    void ResetReading() override;
356
    OGRFeature *GetNextFeature() override;
357
    const OGRFeatureDefn *GetLayerDefn() const override;
358
    bool TestCapability(const char *) const override;
359
};
360
361
/************************************************************************/
362
/*                              Functions                               */
363
/************************************************************************/
364
365
OGRErr OGRSQLiteGetSpatialiteGeometryHeader(const GByte *pabyData, int nBytes,
366
                                            int *pnSRID,
367
                                            OGRwkbGeometryType *peType,
368
                                            bool *pbIsEmpty, double *pdfMinX,
369
                                            double *pdfMinY, double *pdfMaxX,
370
                                            double *pdfMaxY);
371
// CPL_DLL just for spatialite_geom_import_fuzzer
372
OGRErr CPL_DLL OGRSQLiteImportSpatiaLiteGeometry(const GByte *, int,
373
                                                 OGRGeometry **,
374
                                                 int *pnSRID = nullptr);
375
OGRErr OGRSQLiteExportSpatiaLiteGeometry(const OGRGeometry *, GInt32,
376
                                         OGRwkbByteOrder, bool bSpatialite2D,
377
                                         bool bUseComprGeom, GByte **, int *);
378
#endif  // OGR_SQLITE_BASE_H_INCLUDED