Coverage Report

Created: 2026-02-14 09:00

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
336k
#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_None = 0,
38
    OSGF_WKT = 1,
39
    OSGF_WKB = 2,
40
    OSGF_FGF = 3,
41
    OSGF_SpatiaLite = 4
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.87k
        : OGRGeomFieldDefn(pszNameIn, wkbUnknown), m_iCol(iGeomColIn)
53
4.87k
    {
54
4.87k
    }
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_None;
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
46.3k
        : OGRFeatureDefn(pszName)
78
46.3k
    {
79
46.3k
        SetGeomType(wkbNone);
80
46.3k
    }
81
82
    ~OGRSQLiteFeatureDefn() override;
83
84
    OGRSQLiteGeomFieldDefn *myGetGeomFieldDefn(int i)
85
1.00M
    {
86
1.00M
        return cpl::down_cast<OGRSQLiteGeomFieldDefn *>(GetGeomFieldDefn(i));
87
1.00M
    }
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
55.7k
    {
172
55.7k
        return m_aosSavepoints.empty() ? "" : m_aosSavepoints.back();
173
55.7k
    }
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
1.29M
    {
184
1.29M
        return hDB;
185
1.29M
    }
186
187
    sqlite3_vfs *GetVFS()
188
0
    {
189
0
        return pMyVFS;
190
0
    }
191
192
    inline bool GetUpdate() const
193
995k
    {
194
995k
        return eAccess == GA_Update;
195
995k
    }
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
    int 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
10.4k
    {
251
10.4k
        return x * 10000 + y * 100 + z;
252
10.4k
    }
253
254
    int GetSpatialiteVersionNumber();
255
256
    bool SpatialiteRequiresTrustedSchemaOn();
257
    bool AreSpatialiteTriggersSafe();
258
259
    // sqlite3_prepare_v2 error logging wrapper
260
    int
261
    prepareSql(sqlite3 *db,           /* Database handle */
262
               const char *zSql,      /* SQL statement, UTF-8 encoded */
263
               int nByte,             /* Maximum length of zSql in bytes. */
264
               sqlite3_stmt **ppStmt, /* OUT: Statement handle */
265
               const char **pzTail /* OUT: Pointer to unused portion of zSql */
266
    );
267
268
    GDALQueryLoggerFunc pfnQueryLoggerFunc = nullptr;
269
    void *poQueryLoggerArg = nullptr;
270
};
271
272
/************************************************************************/
273
/*                        IOGRSQLiteSelectLayer                         */
274
/************************************************************************/
275
276
class IOGRSQLiteSelectLayer /* non final */
277
{
278
  public:
279
    virtual ~IOGRSQLiteSelectLayer();
280
281
    virtual char *&GetAttrQueryString() = 0;
282
    virtual OGRFeatureQuery *&GetFeatureQuery() = 0;
283
    virtual OGRGeometry *&GetFilterGeom() = 0;
284
    virtual int &GetIGeomFieldFilter() = 0;
285
    virtual const OGRSpatialReference *GetSpatialRef() const = 0;
286
    virtual const OGRFeatureDefn *GetLayerDefn() const = 0;
287
    virtual int InstallFilter(const OGRGeometry *) = 0;
288
    virtual int HasReadFeature() = 0;
289
    virtual void BaseResetReading() = 0;
290
    virtual OGRFeature *BaseGetNextFeature() = 0;
291
    virtual OGRErr BaseSetAttributeFilter(const char *pszQuery) = 0;
292
    virtual GIntBig BaseGetFeatureCount(int bForce) = 0;
293
    virtual int BaseTestCapability(const char *) const = 0;
294
    virtual OGRErr BaseGetExtent(int iGeomField, OGREnvelope *psExtent,
295
                                 bool bForce) = 0;
296
    virtual bool ValidateGeometryFieldIndexForSetSpatialFilter(
297
        int iGeomField, const OGRGeometry *poGeomIn, bool bIsSelectLayer) = 0;
298
};
299
300
/************************************************************************/
301
/*                 OGRSQLiteSelectLayerCommonBehaviour                  */
302
/************************************************************************/
303
304
class OGRSQLiteSelectLayerCommonBehaviour final
305
{
306
    OGRSQLiteBaseDataSource *m_poDS = nullptr;
307
    IOGRSQLiteSelectLayer *m_poLayer = nullptr;
308
309
    CPLString m_osSQLBase{};
310
311
    bool m_bEmptyLayer = false;
312
    bool m_bAllowResetReadingEvenIfIndexAtZero = false;
313
    bool m_bSpatialFilterInSQL = true;
314
315
    std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
316
    GetBaseLayer(size_t &i) const;
317
    int BuildSQL();
318
319
    CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteSelectLayerCommonBehaviour)
320
321
  public:
322
    CPLString m_osSQLCurrent{};
323
324
    OGRSQLiteSelectLayerCommonBehaviour(OGRSQLiteBaseDataSource *poDS,
325
                                        IOGRSQLiteSelectLayer *poBaseLayer,
326
                                        const CPLString &osSQL,
327
                                        bool bEmptyLayer);
328
329
    void ResetReading();
330
    OGRFeature *GetNextFeature();
331
    GIntBig GetFeatureCount(int);
332
    OGRErr SetSpatialFilter(int iGeomField, const OGRGeometry *);
333
    OGRErr SetAttributeFilter(const char *);
334
    int TestCapability(const char *) const;
335
    OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent, bool bForce);
336
};
337
338
/************************************************************************/
339
/*                     OGRSQLiteSingleFeatureLayer                      */
340
/************************************************************************/
341
342
class OGRSQLiteSingleFeatureLayer final : public OGRLayer
343
{
344
  private:
345
    int nVal;
346
    char *pszVal;
347
    OGRFeatureDefn *poFeatureDefn;
348
    int iNextShapeId;
349
350
    CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteSingleFeatureLayer)
351
352
  public:
353
    OGRSQLiteSingleFeatureLayer(const char *pszLayerName, int nVal);
354
    OGRSQLiteSingleFeatureLayer(const char *pszLayerName, const char *pszVal);
355
    ~OGRSQLiteSingleFeatureLayer() override;
356
357
    void ResetReading() override;
358
    OGRFeature *GetNextFeature() override;
359
    const OGRFeatureDefn *GetLayerDefn() const override;
360
    int TestCapability(const char *) const override;
361
};
362
363
/************************************************************************/
364
/*                              Functions                               */
365
/************************************************************************/
366
367
OGRErr OGRSQLiteGetSpatialiteGeometryHeader(const GByte *pabyData, int nBytes,
368
                                            int *pnSRID,
369
                                            OGRwkbGeometryType *peType,
370
                                            bool *pbIsEmpty, double *pdfMinX,
371
                                            double *pdfMinY, double *pdfMaxX,
372
                                            double *pdfMaxY);
373
// CPL_DLL just for spatialite_geom_import_fuzzer
374
OGRErr CPL_DLL OGRSQLiteImportSpatiaLiteGeometry(const GByte *, int,
375
                                                 OGRGeometry **,
376
                                                 int *pnSRID = nullptr);
377
OGRErr OGRSQLiteExportSpatiaLiteGeometry(const OGRGeometry *, GInt32,
378
                                         OGRwkbByteOrder, bool bSpatialite2D,
379
                                         bool bUseComprGeom, GByte **, int *);
380
#endif  // OGR_SQLITE_BASE_H_INCLUDED