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 926 : OGRSQLiteGeomFieldDefn(const char *pszNameIn, int iGeomColIn)
52 926 : : OGRGeomFieldDefn(pszNameIn, wkbUnknown), m_iCol(iGeomColIn)
53 : {
54 926 : }
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 3889 : explicit OGRSQLiteFeatureDefn(const char *pszName = nullptr)
75 3889 : : OGRFeatureDefn(pszName)
76 : {
77 3889 : SetGeomType(wkbNone);
78 3889 : }
79 :
80 7692 : OGRSQLiteGeomFieldDefn *myGetGeomFieldDefn(int i)
81 : {
82 7692 : return cpl::down_cast<OGRSQLiteGeomFieldDefn *>(GetGeomFieldDefn(i));
83 : }
84 : };
85 :
86 : /************************************************************************/
87 : /* IOGRSQLiteGetSpatialWhere */
88 : /************************************************************************/
89 :
90 : class IOGRSQLiteGetSpatialWhere
91 : {
92 : public:
93 8420 : virtual ~IOGRSQLiteGetSpatialWhere()
94 8420 : {
95 8420 : }
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 3550 : 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 bUserTransactionActive = FALSE;
147 : int nSoftTransactionLevel = 0;
148 :
149 : OGRErr DoTransactionCommand(const char *pszCommand);
150 :
151 : bool DealWithOgrSchemaOpenOption(CSLConstList papszOpenOptionsIn);
152 :
153 : CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteBaseDataSource)
154 :
155 : public:
156 : OGRSQLiteBaseDataSource();
157 : virtual ~OGRSQLiteBaseDataSource();
158 :
159 316688 : sqlite3 *GetDB()
160 : {
161 316688 : return hDB;
162 : }
163 :
164 72 : sqlite3_vfs *GetVFS()
165 : {
166 72 : return pMyVFS;
167 : }
168 :
169 296620 : inline bool GetUpdate() const
170 : {
171 296620 : return eAccess == GA_Update;
172 : }
173 :
174 3 : VSILFILE *GetVSILFILE() const
175 : {
176 3 : return fpMainFile;
177 : }
178 :
179 : void NotifyFileOpened(const char *pszFilename, VSILFILE *fp);
180 :
181 : const OGREnvelope *GetEnvelopeFromSQL(const CPLString &osSQL);
182 : void SetEnvelopeForSQL(const CPLString &osSQL,
183 : const OGREnvelope &oEnvelope);
184 :
185 : virtual std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
186 : GetLayerWithGetSpatialWhereByName(const char *pszName) = 0;
187 :
188 : virtual OGRErr AbortSQL() override;
189 : bool SetQueryLoggerFunc(GDALQueryLoggerFunc pfnQueryLoggerFuncIn,
190 : void *poQueryLoggerArgIn) override;
191 :
192 : virtual OGRErr StartTransaction(int bForce = FALSE) override;
193 : virtual OGRErr CommitTransaction() override;
194 : virtual OGRErr RollbackTransaction() override;
195 :
196 : virtual int TestCapability(const char *) override;
197 :
198 : virtual void *GetInternalHandle(const char *) override;
199 :
200 : OGRErr SoftStartTransaction();
201 : OGRErr SoftCommitTransaction();
202 : OGRErr SoftRollbackTransaction();
203 :
204 : OGRErr PragmaCheck(const char *pszPragma, const char *pszExpected,
205 : int nRowsExpected);
206 :
207 : virtual void LoadRelationships() const;
208 : void LoadRelationshipsFromForeignKeys(
209 : const std::vector<std::string> &excludedTables) const;
210 : std::vector<std::string>
211 : GetRelationshipNames(CSLConstList papszOptions = nullptr) const override;
212 : const GDALRelationship *
213 : GetRelationship(const std::string &name) const override;
214 :
215 : bool IsSpatialiteLoaded();
216 :
217 12108 : static int MakeSpatialiteVersionNumber(int x, int y, int z)
218 : {
219 12108 : return x * 10000 + y * 100 + z;
220 : }
221 :
222 : int GetSpatialiteVersionNumber();
223 :
224 : bool SpatialiteRequiresTrustedSchemaOn();
225 : bool AreSpatialiteTriggersSafe();
226 :
227 : // sqlite3_prepare_v2 error logging wrapper
228 : int
229 : prepareSql(sqlite3 *db, /* Database handle */
230 : const char *zSql, /* SQL statement, UTF-8 encoded */
231 : int nByte, /* Maximum length of zSql in bytes. */
232 : sqlite3_stmt **ppStmt, /* OUT: Statement handle */
233 : const char **pzTail /* OUT: Pointer to unused portion of zSql */
234 : );
235 :
236 : GDALQueryLoggerFunc pfnQueryLoggerFunc = nullptr;
237 : void *poQueryLoggerArg = nullptr;
238 : };
239 :
240 : /************************************************************************/
241 : /* IOGRSQLiteSelectLayer */
242 : /************************************************************************/
243 :
244 : class IOGRSQLiteSelectLayer
245 : {
246 : public:
247 2340 : virtual ~IOGRSQLiteSelectLayer()
248 2340 : {
249 2340 : }
250 :
251 : virtual char *&GetAttrQueryString() = 0;
252 : virtual OGRFeatureQuery *&GetFeatureQuery() = 0;
253 : virtual OGRGeometry *&GetFilterGeom() = 0;
254 : virtual int &GetIGeomFieldFilter() = 0;
255 : virtual OGRSpatialReference *GetSpatialRef() = 0;
256 : virtual OGRFeatureDefn *GetLayerDefn() = 0;
257 : virtual int InstallFilter(OGRGeometry *) = 0;
258 : virtual int HasReadFeature() = 0;
259 : virtual void BaseResetReading() = 0;
260 : virtual OGRFeature *BaseGetNextFeature() = 0;
261 : virtual OGRErr BaseSetAttributeFilter(const char *pszQuery) = 0;
262 : virtual GIntBig BaseGetFeatureCount(int bForce) = 0;
263 : virtual int BaseTestCapability(const char *) = 0;
264 : virtual OGRErr BaseGetExtent(OGREnvelope *psExtent, int bForce) = 0;
265 : virtual OGRErr BaseGetExtent(int iGeomField, OGREnvelope *psExtent,
266 : int bForce) = 0;
267 : virtual bool ValidateGeometryFieldIndexForSetSpatialFilter(
268 : int iGeomField, const OGRGeometry *poGeomIn, bool bIsSelectLayer) = 0;
269 : };
270 :
271 : /************************************************************************/
272 : /* OGRSQLiteSelectLayerCommonBehaviour */
273 : /************************************************************************/
274 :
275 : class OGRSQLiteSelectLayerCommonBehaviour
276 : {
277 : OGRSQLiteBaseDataSource *m_poDS = nullptr;
278 : IOGRSQLiteSelectLayer *m_poLayer = nullptr;
279 :
280 : CPLString m_osSQLBase{};
281 :
282 : bool m_bEmptyLayer = false;
283 : bool m_bAllowResetReadingEvenIfIndexAtZero = false;
284 : bool m_bSpatialFilterInSQL = true;
285 :
286 : std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *> GetBaseLayer(size_t &i);
287 : int BuildSQL();
288 :
289 : CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteSelectLayerCommonBehaviour)
290 :
291 : public:
292 : CPLString m_osSQLCurrent{};
293 :
294 : OGRSQLiteSelectLayerCommonBehaviour(OGRSQLiteBaseDataSource *poDS,
295 : IOGRSQLiteSelectLayer *poBaseLayer,
296 : const CPLString &osSQL,
297 : bool bEmptyLayer);
298 :
299 : void ResetReading();
300 : OGRFeature *GetNextFeature();
301 : GIntBig GetFeatureCount(int);
302 : void SetSpatialFilter(int iGeomField, OGRGeometry *);
303 : OGRErr SetAttributeFilter(const char *);
304 : int TestCapability(const char *);
305 : OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce);
306 : };
307 :
308 : /************************************************************************/
309 : /* OGRSQLiteSingleFeatureLayer */
310 : /************************************************************************/
311 :
312 : class OGRSQLiteSingleFeatureLayer final : public OGRLayer
313 : {
314 : private:
315 : int nVal;
316 : char *pszVal;
317 : OGRFeatureDefn *poFeatureDefn;
318 : int iNextShapeId;
319 :
320 : CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteSingleFeatureLayer)
321 :
322 : public:
323 : OGRSQLiteSingleFeatureLayer(const char *pszLayerName, int nVal);
324 : OGRSQLiteSingleFeatureLayer(const char *pszLayerName, const char *pszVal);
325 : virtual ~OGRSQLiteSingleFeatureLayer();
326 :
327 : virtual void ResetReading() override;
328 : virtual OGRFeature *GetNextFeature() override;
329 : virtual OGRFeatureDefn *GetLayerDefn() override;
330 : virtual int TestCapability(const char *) override;
331 : };
332 :
333 : /************************************************************************/
334 : /* Functions */
335 : /************************************************************************/
336 :
337 : OGRErr OGRSQLiteGetSpatialiteGeometryHeader(const GByte *pabyData, int nBytes,
338 : int *pnSRID,
339 : OGRwkbGeometryType *peType,
340 : bool *pbIsEmpty, double *pdfMinX,
341 : double *pdfMinY, double *pdfMaxX,
342 : double *pdfMaxY);
343 : // CPL_DLL just for spatialite_geom_import_fuzzer
344 : OGRErr CPL_DLL OGRSQLiteImportSpatiaLiteGeometry(const GByte *, int,
345 : OGRGeometry **,
346 : int *pnSRID = nullptr);
347 : OGRErr OGRSQLiteExportSpatiaLiteGeometry(const OGRGeometry *, GInt32,
348 : OGRwkbByteOrder, bool bSpatialite2D,
349 : bool bUseComprGeom, GByte **, int *);
350 : #endif // OGR_SQLITE_BASE_H_INCLUDED
|