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 1798 : class OGRSQLiteGeomFieldDefn final : public OGRGeomFieldDefn
49 : {
50 : public:
51 899 : OGRSQLiteGeomFieldDefn(const char *pszNameIn, int iGeomColIn)
52 899 : : OGRGeomFieldDefn(pszNameIn, wkbUnknown), m_iCol(iGeomColIn)
53 : {
54 899 : }
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 7266 : class OGRSQLiteFeatureDefn final : public OGRFeatureDefn
74 : {
75 : public:
76 3633 : explicit OGRSQLiteFeatureDefn(const char *pszName = nullptr)
77 3633 : : OGRFeatureDefn(pszName)
78 : {
79 3633 : SetGeomType(wkbNone);
80 3633 : }
81 :
82 : ~OGRSQLiteFeatureDefn() override;
83 :
84 7762 : OGRSQLiteGeomFieldDefn *myGetGeomFieldDefn(int i)
85 : {
86 7762 : return cpl::down_cast<OGRSQLiteGeomFieldDefn *>(GetGeomFieldDefn(i));
87 : }
88 : };
89 :
90 : /************************************************************************/
91 : /* IOGRSQLiteGetSpatialWhere */
92 : /************************************************************************/
93 :
94 7967 : class IOGRSQLiteGetSpatialWhere
95 : {
96 : public:
97 : virtual ~IOGRSQLiteGetSpatialWhere();
98 :
99 : virtual bool HasFastSpatialFilter(int iGeomCol) = 0;
100 : virtual CPLString GetSpatialWhere(int iGeomCol,
101 : OGRGeometry *poFilterGeom) = 0;
102 : };
103 :
104 : /************************************************************************/
105 : /* OGRSQLiteBaseDataSource */
106 : /************************************************************************/
107 :
108 : /* Used by both OGRSQLiteDataSource and OGRGeoPackageDataSource */
109 3703 : class OGRSQLiteBaseDataSource CPL_NON_FINAL : public GDALPamDataset
110 : {
111 : protected:
112 : char *m_pszFilename = nullptr;
113 : std::string
114 : m_osFilenameForSQLiteOpen{}; // generally m_pszFilename, but can be
115 : // also file:{m_pszFilename}?nolock=1
116 : bool m_bNoLock = false;
117 : std::string
118 : m_osFinalFilename{}; // use when generating a network hosted file with
119 : // CPL_VSIL_USE_TEMP_FILE_FOR_RANDOM_WRITE=YES
120 : bool m_bCallUndeclareFileNotToOpen = false;
121 :
122 : sqlite3 *hDB = nullptr;
123 :
124 : sqlite3_vfs *pMyVFS = nullptr;
125 :
126 : VSILFILE *fpMainFile =
127 : nullptr; /* Set by the VFS layer when it opens the DB */
128 : /* Must *NOT* be closed by the datasource explicitly. */
129 :
130 : bool OpenOrCreateDB(int flags, bool bRegisterOGR2SQLiteExtensions,
131 : bool bLoadExtensions);
132 : bool SetSynchronous();
133 : bool SetCacheSize();
134 : void LoadExtensions();
135 :
136 : bool CloseDB();
137 :
138 : std::map<CPLString, OGREnvelope> oMapSQLEnvelope{};
139 :
140 : mutable bool m_bHasPopulatedRelationships = false;
141 : mutable std::map<std::string, std::unique_ptr<GDALRelationship>>
142 : m_osMapRelationships{};
143 :
144 : void *hSpatialiteCtxt = nullptr;
145 : bool InitSpatialite();
146 : void FinishSpatialite();
147 :
148 : int m_bUserTransactionActive = FALSE;
149 : int m_nSoftTransactionLevel = 0;
150 : std::vector<std::string> m_aosSavepoints{};
151 : // The transaction was implicitly started by SAVEPOINT
152 : bool m_bImplicitTransactionOpened = false;
153 :
154 : OGRErr DoTransactionCommand(const char *pszCommand);
155 :
156 : bool DealWithOgrSchemaOpenOption(CSLConstList papszOpenOptionsIn);
157 :
158 : CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteBaseDataSource)
159 :
160 : public:
161 : OGRSQLiteBaseDataSource();
162 : virtual ~OGRSQLiteBaseDataSource();
163 :
164 1630 : std::string GetCurrentSavepoint() const
165 : {
166 1630 : return m_aosSavepoints.empty() ? "" : m_aosSavepoints.back();
167 : }
168 :
169 : std::string GetFirstSavepoint() const
170 : {
171 : return m_aosSavepoints.empty() ? "" : m_aosSavepoints.front();
172 : }
173 :
174 : bool IsInTransaction() const;
175 :
176 319502 : sqlite3 *GetDB()
177 : {
178 319502 : return hDB;
179 : }
180 :
181 72 : sqlite3_vfs *GetVFS()
182 : {
183 72 : return pMyVFS;
184 : }
185 :
186 300306 : inline bool GetUpdate() const
187 : {
188 300306 : return eAccess == GA_Update;
189 : }
190 :
191 3 : VSILFILE *GetVSILFILE() const
192 : {
193 3 : return fpMainFile;
194 : }
195 :
196 : void NotifyFileOpened(const char *pszFilename, VSILFILE *fp);
197 :
198 : const OGREnvelope *GetEnvelopeFromSQL(const CPLString &osSQL);
199 : void SetEnvelopeForSQL(const CPLString &osSQL,
200 : const OGREnvelope &oEnvelope);
201 :
202 : virtual std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
203 : GetLayerWithGetSpatialWhereByName(const char *pszName) = 0;
204 :
205 : virtual OGRErr AbortSQL() override;
206 : bool SetQueryLoggerFunc(GDALQueryLoggerFunc pfnQueryLoggerFuncIn,
207 : void *poQueryLoggerArgIn) override;
208 :
209 : virtual OGRErr StartTransaction(int bForce = FALSE) override;
210 : virtual OGRErr CommitTransaction() override;
211 : virtual OGRErr RollbackTransaction() override;
212 :
213 : virtual int TestCapability(const char *) override;
214 :
215 : virtual void *GetInternalHandle(const char *) override;
216 :
217 : OGRErr SoftStartTransaction();
218 : OGRErr SoftCommitTransaction();
219 : OGRErr SoftRollbackTransaction();
220 : OGRErr StartSavepoint(const std::string &osName);
221 : OGRErr ReleaseSavepoint(const std::string &osName);
222 : OGRErr RollbackToSavepoint(const std::string &osName);
223 :
224 : /**
225 : * Execute a SQL transaction command (BEGIN, COMMIT, ROLLBACK, SAVEPOINT)
226 : * @return TRUE if the osSQLCommand was recognized as a transaction command
227 : */
228 : bool ProcessTransactionSQL(const std::string &osSQLCommand);
229 :
230 : OGRErr PragmaCheck(const char *pszPragma, const char *pszExpected,
231 : int nRowsExpected);
232 :
233 : virtual void LoadRelationships() const;
234 : void LoadRelationshipsFromForeignKeys(
235 : const std::vector<std::string> &excludedTables) const;
236 : std::vector<std::string>
237 : GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
238 : const GDALRelationship *
239 : GetRelationship(const std::string &name) const override;
240 :
241 : bool IsSpatialiteLoaded();
242 :
243 10638 : static int MakeSpatialiteVersionNumber(int x, int y, int z)
244 : {
245 10638 : return x * 10000 + y * 100 + z;
246 : }
247 :
248 : int GetSpatialiteVersionNumber();
249 :
250 : bool SpatialiteRequiresTrustedSchemaOn();
251 : bool AreSpatialiteTriggersSafe();
252 :
253 : // sqlite3_prepare_v2 error logging wrapper
254 : int
255 : prepareSql(sqlite3 *db, /* Database handle */
256 : const char *zSql, /* SQL statement, UTF-8 encoded */
257 : int nByte, /* Maximum length of zSql in bytes. */
258 : sqlite3_stmt **ppStmt, /* OUT: Statement handle */
259 : const char **pzTail /* OUT: Pointer to unused portion of zSql */
260 : );
261 :
262 : GDALQueryLoggerFunc pfnQueryLoggerFunc = nullptr;
263 : void *poQueryLoggerArg = nullptr;
264 : };
265 :
266 : /************************************************************************/
267 : /* IOGRSQLiteSelectLayer */
268 : /************************************************************************/
269 :
270 2217 : class IOGRSQLiteSelectLayer
271 : {
272 : public:
273 : virtual ~IOGRSQLiteSelectLayer();
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
|