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