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