Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements OGRSQLiteDataSource class.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : *
9 : * Contributor: Alessandro Furieri, a.furieri@lqt.it
10 : * Portions of this module properly supporting SpatiaLite Table/Geom creation
11 : * Developed for Faunalia ( http://www.faunalia.it) with funding from
12 : * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
13 : *
14 : ******************************************************************************
15 : * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
16 : * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
17 : *
18 : * SPDX-License-Identifier: MIT
19 : ****************************************************************************/
20 :
21 : #include "cpl_port.h"
22 : #include "ogr_sqlite.h"
23 : #include "ogrsqlitevirtualogr.h"
24 : #include "ogrsqliteutility.h"
25 : #include "ogrsqlitevfs.h"
26 :
27 : #include <cctype>
28 : #include <cstddef>
29 : #include <cstdio>
30 : #include <cstdlib>
31 : #include <cstring>
32 : #include <sys/stat.h>
33 : #include <map>
34 : #include <mutex>
35 : #include <set>
36 : #include <sstream>
37 : #include <string>
38 : #include <utility>
39 : #include <vector>
40 :
41 : #include "cpl_conv.h"
42 : #include "cpl_error.h"
43 : #include "cpl_hash_set.h"
44 : #include "cpl_multiproc.h"
45 : #include "cpl_string.h"
46 : #include "cpl_vsi.h"
47 : #include "gdal.h"
48 : #include "gdal_pam.h"
49 : #include "gdal_priv.h"
50 : #include "ogr_core.h"
51 : #include "ogr_feature.h"
52 : #include "ogr_geometry.h"
53 : #include "ogr_spatialref.h"
54 : #include "ogr_schema_override.h"
55 : #include "ogrsf_frmts.h"
56 : #include "sqlite3.h"
57 :
58 : #include "proj.h"
59 : #include "ogr_proj_p.h"
60 :
61 : #ifdef __clang__
62 : #pragma clang diagnostic push
63 : #pragma clang diagnostic ignored "-Wunknown-pragmas"
64 : #pragma clang diagnostic ignored "-Wdocumentation"
65 : #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
66 : #endif
67 :
68 : #if defined(HAVE_SPATIALITE) && !defined(SPATIALITE_DLOPEN)
69 : #include "spatialite.h"
70 : #endif
71 :
72 : #ifdef __clang__
73 : #pragma clang diagnostic pop
74 : #endif
75 :
76 : #undef SQLITE_STATIC
77 : #define SQLITE_STATIC (static_cast<sqlite3_destructor_type>(nullptr))
78 :
79 : // Keep in sync prototype of those 2 functions between gdalopeninfo.cpp,
80 : // ogrsqlitedatasource.cpp and ogrgeopackagedatasource.cpp
81 : void GDALOpenInfoDeclareFileNotToOpen(const char *pszFilename,
82 : const GByte *pabyHeader,
83 : int nHeaderBytes);
84 : void GDALOpenInfoUnDeclareFileNotToOpen(const char *pszFilename);
85 :
86 : #ifdef HAVE_SPATIALITE
87 :
88 : #ifdef SPATIALITE_DLOPEN
89 : static CPLMutex *hMutexLoadSpatialiteSymbols = nullptr;
90 : static void *(*pfn_spatialite_alloc_connection)(void) = nullptr;
91 : static void (*pfn_spatialite_shutdown)(void) = nullptr;
92 : static void (*pfn_spatialite_init_ex)(sqlite3 *, const void *, int) = nullptr;
93 : static void (*pfn_spatialite_cleanup_ex)(const void *) = nullptr;
94 : static const char *(*pfn_spatialite_version)(void) = nullptr;
95 : #else
96 : static void *(*pfn_spatialite_alloc_connection)(void) =
97 : spatialite_alloc_connection;
98 : static void (*pfn_spatialite_shutdown)(void) = spatialite_shutdown;
99 : static void (*pfn_spatialite_init_ex)(sqlite3 *, const void *,
100 : int) = spatialite_init_ex;
101 : static void (*pfn_spatialite_cleanup_ex)(const void *) = spatialite_cleanup_ex;
102 : static const char *(*pfn_spatialite_version)(void) = spatialite_version;
103 : #endif
104 :
105 : #ifndef SPATIALITE_SONAME
106 : #define SPATIALITE_SONAME "libspatialite.so"
107 : #endif
108 :
109 : #ifdef SPATIALITE_DLOPEN
110 : static bool OGRSQLiteLoadSpatialiteSymbols()
111 : {
112 : static bool bInitializationDone = false;
113 : CPLMutexHolderD(&hMutexLoadSpatialiteSymbols);
114 : if (bInitializationDone)
115 : return pfn_spatialite_alloc_connection != nullptr;
116 : bInitializationDone = true;
117 :
118 : const char *pszLibName =
119 : CPLGetConfigOption("SPATIALITESO", SPATIALITE_SONAME);
120 : CPLPushErrorHandler(CPLQuietErrorHandler);
121 :
122 : /* coverity[tainted_string] */
123 : pfn_spatialite_alloc_connection = (void *(*)(void))CPLGetSymbol(
124 : pszLibName, "spatialite_alloc_connection");
125 : CPLPopErrorHandler();
126 :
127 : if (pfn_spatialite_alloc_connection == nullptr)
128 : {
129 : CPLDebug("SQLITE", "Cannot find %s in %s",
130 : "spatialite_alloc_connection", pszLibName);
131 : return false;
132 : }
133 :
134 : pfn_spatialite_shutdown =
135 : (void (*)(void))CPLGetSymbol(pszLibName, "spatialite_shutdown");
136 : pfn_spatialite_init_ex =
137 : (void (*)(sqlite3 *, const void *, int))CPLGetSymbol(
138 : pszLibName, "spatialite_init_ex");
139 : pfn_spatialite_cleanup_ex = (void (*)(const void *))CPLGetSymbol(
140 : pszLibName, "spatialite_cleanup_ex");
141 : pfn_spatialite_version =
142 : (const char *(*)(void))CPLGetSymbol(pszLibName, "spatialite_version");
143 : if (pfn_spatialite_shutdown == nullptr ||
144 : pfn_spatialite_init_ex == nullptr ||
145 : pfn_spatialite_cleanup_ex == nullptr ||
146 : pfn_spatialite_version == nullptr)
147 : {
148 : pfn_spatialite_shutdown = nullptr;
149 : pfn_spatialite_init_ex = nullptr;
150 : pfn_spatialite_cleanup_ex = nullptr;
151 : pfn_spatialite_version = nullptr;
152 : return false;
153 : }
154 : return true;
155 : }
156 : #endif
157 :
158 : /************************************************************************/
159 : /* InitSpatialite() */
160 : /************************************************************************/
161 :
162 4150 : bool OGRSQLiteBaseDataSource::InitSpatialite()
163 : {
164 7836 : if (hSpatialiteCtxt == nullptr &&
165 3686 : CPLTestBool(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")))
166 : {
167 : #ifdef SPATIALITE_DLOPEN
168 : if (!OGRSQLiteLoadSpatialiteSymbols())
169 : return false;
170 : #endif
171 3686 : CPLAssert(hSpatialiteCtxt == nullptr);
172 3686 : hSpatialiteCtxt = pfn_spatialite_alloc_connection();
173 3686 : if (hSpatialiteCtxt != nullptr)
174 : {
175 7372 : pfn_spatialite_init_ex(hDB, hSpatialiteCtxt,
176 3686 : CPLTestBool(CPLGetConfigOption(
177 : "SPATIALITE_INIT_VERBOSE", "FALSE")));
178 : }
179 : }
180 4150 : return hSpatialiteCtxt != nullptr;
181 : }
182 :
183 : /************************************************************************/
184 : /* FinishSpatialite() */
185 : /************************************************************************/
186 :
187 4170 : void OGRSQLiteBaseDataSource::FinishSpatialite()
188 : {
189 : // Current implementation of spatialite_cleanup_ex() (as of libspatialite 5.1)
190 : // is not re-entrant due to the use of xmlCleanupParser()
191 : // Cf https://groups.google.com/g/spatialite-users/c/tsfZ_GDrRKs/m/aj-Dt4xoBQAJ?utm_medium=email&utm_source=footer
192 : static std::mutex oCleanupMutex;
193 8340 : std::lock_guard oLock(oCleanupMutex);
194 :
195 4170 : if (hSpatialiteCtxt != nullptr)
196 : {
197 3685 : pfn_spatialite_cleanup_ex(hSpatialiteCtxt);
198 3685 : hSpatialiteCtxt = nullptr;
199 : }
200 4170 : }
201 :
202 : /************************************************************************/
203 : /* IsSpatialiteLoaded() */
204 : /************************************************************************/
205 :
206 11908 : bool OGRSQLiteBaseDataSource::IsSpatialiteLoaded()
207 : {
208 11908 : return hSpatialiteCtxt != nullptr;
209 : }
210 :
211 : #else
212 :
213 : bool OGRSQLiteBaseDataSource::InitSpatialite()
214 : {
215 : return false;
216 : }
217 :
218 : void OGRSQLiteBaseDataSource::FinishSpatialite()
219 : {
220 : }
221 :
222 : bool OGRSQLiteBaseDataSource::IsSpatialiteLoaded()
223 : {
224 : return false;
225 : }
226 :
227 : #endif
228 :
229 : /************************************************************************/
230 : /* OGRSQLiteDriverUnload() */
231 : /************************************************************************/
232 :
233 1263 : void OGRSQLiteDriverUnload(GDALDriver *)
234 : {
235 : #ifdef HAVE_SPATIALITE
236 1263 : if (pfn_spatialite_shutdown != nullptr)
237 1263 : pfn_spatialite_shutdown();
238 : #ifdef SPATIALITE_DLOPEN
239 : if (hMutexLoadSpatialiteSymbols != nullptr)
240 : {
241 : CPLDestroyMutex(hMutexLoadSpatialiteSymbols);
242 : hMutexLoadSpatialiteSymbols = nullptr;
243 : }
244 : #endif
245 : #endif
246 1263 : }
247 :
248 : /************************************************************************/
249 : /* DealWithOgrSchemaOpenOption() */
250 : /************************************************************************/
251 1197 : bool OGRSQLiteBaseDataSource::DealWithOgrSchemaOpenOption(
252 : CSLConstList papszOpenOptionsIn)
253 : {
254 : const std::string osFieldsSchemaOverrideParam =
255 2394 : CSLFetchNameValueDef(papszOpenOptionsIn, "OGR_SCHEMA", "");
256 :
257 1197 : if (!osFieldsSchemaOverrideParam.empty())
258 : {
259 9 : if (GetUpdate())
260 : {
261 0 : CPLError(CE_Failure, CPLE_NotSupported,
262 : "OGR_SCHEMA open option is not supported in update mode.");
263 4 : return false;
264 : }
265 :
266 9 : OGRSchemaOverride oSchemaOverride;
267 9 : const auto nErrorCount = CPLGetErrorCounter();
268 17 : if (!oSchemaOverride.LoadFromJSON(osFieldsSchemaOverrideParam) ||
269 8 : !oSchemaOverride.IsValid())
270 : {
271 1 : if (nErrorCount == CPLGetErrorCounter())
272 : {
273 0 : CPLError(CE_Failure, CPLE_AppDefined,
274 : "Content of OGR_SCHEMA in %s is not valid",
275 : osFieldsSchemaOverrideParam.c_str());
276 : }
277 1 : return false;
278 : }
279 :
280 8 : if (!oSchemaOverride.DefaultApply(this, "SQLite"))
281 3 : return false;
282 : }
283 1193 : return true;
284 : }
285 :
286 : /************************************************************************/
287 : /* GetSpatialiteVersionNumber() */
288 : /************************************************************************/
289 :
290 5515 : int OGRSQLiteBaseDataSource::GetSpatialiteVersionNumber()
291 : {
292 5515 : int v = 0;
293 : #ifdef HAVE_SPATIALITE
294 5515 : if (IsSpatialiteLoaded())
295 : {
296 : const CPLStringList aosTokens(
297 10914 : CSLTokenizeString2(pfn_spatialite_version(), ".", 0));
298 5457 : if (aosTokens.size() >= 2)
299 : {
300 5457 : v = MakeSpatialiteVersionNumber(
301 : atoi(aosTokens[0]), atoi(aosTokens[1]),
302 5457 : aosTokens.size() == 3 ? atoi(aosTokens[2]) : 0);
303 : }
304 : }
305 : #endif
306 5515 : return v;
307 : }
308 :
309 : /************************************************************************/
310 : /* AddRelationship() */
311 : /************************************************************************/
312 :
313 15 : bool OGRSQLiteDataSource::AddRelationship(
314 : std::unique_ptr<GDALRelationship> &&relationship,
315 : std::string &failureReason)
316 : {
317 15 : if (!GetUpdate())
318 : {
319 0 : CPLError(CE_Failure, CPLE_NotSupported,
320 : "AddRelationship() not supported on read-only dataset");
321 0 : return false;
322 : }
323 :
324 15 : if (!ValidateRelationship(relationship.get(), failureReason))
325 : {
326 12 : return false;
327 : }
328 :
329 3 : const std::string &osLeftTableName = relationship->GetLeftTableName();
330 3 : const std::string &osRightTableName = relationship->GetRightTableName();
331 3 : const auto &aosLeftTableFields = relationship->GetLeftTableFields();
332 3 : const auto &aosRightTableFields = relationship->GetRightTableFields();
333 :
334 3 : bool bBaseKeyIsUnique = false;
335 : {
336 : const std::set<std::string> uniqueBaseFieldsUC =
337 6 : SQLGetUniqueFieldUCConstraints(GetDB(), osLeftTableName.c_str());
338 9 : if (cpl::contains(uniqueBaseFieldsUC,
339 3 : CPLString(aosLeftTableFields[0]).toupper()))
340 : {
341 2 : bBaseKeyIsUnique = true;
342 : }
343 : }
344 3 : if (!bBaseKeyIsUnique)
345 : {
346 : failureReason = "Base table field must be a primary key field or have "
347 1 : "a unique constraint set";
348 1 : return false;
349 : }
350 :
351 0 : OGRSQLiteTableLayer *poRightTable = dynamic_cast<OGRSQLiteTableLayer *>(
352 2 : GetLayerByName(osRightTableName.c_str()));
353 2 : if (!poRightTable)
354 : {
355 0 : failureReason = ("Right table " + osRightTableName +
356 : " is not an existing layer in the dataset")
357 0 : .c_str();
358 0 : return false;
359 : }
360 :
361 2 : char *pszForeignKeySQL = nullptr;
362 2 : if (relationship->GetType() == GDALRelationshipType::GRT_ASSOCIATION)
363 : {
364 2 : pszForeignKeySQL = sqlite3_mprintf(
365 : "FOREIGN KEY(\"%w\") REFERENCES \"%w\"(\"%w\") DEFERRABLE "
366 : "INITIALLY DEFERRED",
367 1 : aosRightTableFields[0].c_str(), osLeftTableName.c_str(),
368 1 : aosLeftTableFields[0].c_str());
369 : }
370 : else
371 : {
372 2 : pszForeignKeySQL = sqlite3_mprintf(
373 : "FOREIGN KEY(\"%w\") REFERENCES \"%w\"(\"%w\") ON DELETE CASCADE "
374 : "ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED",
375 1 : aosRightTableFields[0].c_str(), osLeftTableName.c_str(),
376 1 : aosLeftTableFields[0].c_str());
377 : }
378 :
379 2 : int eErr = poRightTable->AddForeignKeysToTable(pszForeignKeySQL);
380 2 : sqlite3_free(pszForeignKeySQL);
381 2 : if (eErr != OGRERR_NONE)
382 : {
383 0 : failureReason = "Could not add foreign keys to table";
384 0 : return false;
385 : }
386 :
387 2 : char *pszSQL = sqlite3_mprintf(
388 : "CREATE INDEX \"idx_%qw_related_id\" ON \"%w\" (\"%w\");",
389 : osRightTableName.c_str(), osRightTableName.c_str(),
390 2 : aosRightTableFields[0].c_str());
391 2 : eErr = SQLCommand(hDB, pszSQL);
392 2 : sqlite3_free(pszSQL);
393 2 : if (eErr != OGRERR_NONE)
394 : {
395 0 : failureReason = ("Could not create index for " + osRightTableName +
396 0 : " " + aosRightTableFields[0])
397 0 : .c_str();
398 0 : return false;
399 : }
400 :
401 2 : m_bHasPopulatedRelationships = false;
402 2 : m_osMapRelationships.clear();
403 2 : return true;
404 : }
405 :
406 : /************************************************************************/
407 : /* ValidateRelationship() */
408 : /************************************************************************/
409 :
410 15 : bool OGRSQLiteDataSource::ValidateRelationship(
411 : const GDALRelationship *poRelationship, std::string &failureReason)
412 : {
413 :
414 15 : if (poRelationship->GetCardinality() !=
415 : GDALRelationshipCardinality::GRC_ONE_TO_MANY)
416 : {
417 : failureReason = "Only one to many relationships are supported for "
418 3 : "SQLITE datasources";
419 3 : return false;
420 : }
421 :
422 23 : if (poRelationship->GetType() != GDALRelationshipType::GRT_COMPOSITE &&
423 11 : poRelationship->GetType() != GDALRelationshipType::GRT_ASSOCIATION)
424 : {
425 : failureReason = "Only association and composite relationship types are "
426 0 : "supported for SQLITE datasources";
427 0 : return false;
428 : }
429 :
430 12 : const std::string &osLeftTableName = poRelationship->GetLeftTableName();
431 12 : OGRLayer *poLeftTable = GetLayerByName(osLeftTableName.c_str());
432 12 : if (!poLeftTable)
433 : {
434 2 : failureReason = ("Left table " + osLeftTableName +
435 : " is not an existing layer in the dataset")
436 1 : .c_str();
437 1 : return false;
438 : }
439 11 : const std::string &osRightTableName = poRelationship->GetRightTableName();
440 11 : OGRLayer *poRightTable = GetLayerByName(osRightTableName.c_str());
441 11 : if (!poRightTable)
442 : {
443 2 : failureReason = ("Right table " + osRightTableName +
444 : " is not an existing layer in the dataset")
445 1 : .c_str();
446 1 : return false;
447 : }
448 :
449 10 : const auto &aosLeftTableFields = poRelationship->GetLeftTableFields();
450 10 : if (aosLeftTableFields.empty())
451 : {
452 1 : failureReason = "No left table fields were specified";
453 1 : return false;
454 : }
455 9 : else if (aosLeftTableFields.size() > 1)
456 : {
457 : failureReason = "Only a single left table field is permitted for the "
458 1 : "SQLITE relationships";
459 1 : return false;
460 : }
461 : else
462 : {
463 : // validate left field exists
464 16 : if (poLeftTable->GetLayerDefn()->GetFieldIndex(
465 17 : aosLeftTableFields[0].c_str()) < 0 &&
466 1 : !EQUAL(poLeftTable->GetFIDColumn(), aosLeftTableFields[0].c_str()))
467 : {
468 2 : failureReason = ("Left table field " + aosLeftTableFields[0] +
469 2 : " does not exist in " + osLeftTableName)
470 1 : .c_str();
471 1 : return false;
472 : }
473 : }
474 :
475 7 : const auto &aosRightTableFields = poRelationship->GetRightTableFields();
476 7 : if (aosRightTableFields.empty())
477 : {
478 1 : failureReason = "No right table fields were specified";
479 1 : return false;
480 : }
481 6 : else if (aosRightTableFields.size() > 1)
482 : {
483 : failureReason = "Only a single right table field is permitted for the "
484 1 : "SQLITE relationships";
485 1 : return false;
486 : }
487 : else
488 : {
489 : // validate right field exists
490 10 : if (poRightTable->GetLayerDefn()->GetFieldIndex(
491 11 : aosRightTableFields[0].c_str()) < 0 &&
492 1 : !EQUAL(poRightTable->GetFIDColumn(),
493 : aosRightTableFields[0].c_str()))
494 : {
495 2 : failureReason = ("Right table field " + aosRightTableFields[0] +
496 2 : " does not exist in " + osRightTableName)
497 1 : .c_str();
498 1 : return false;
499 : }
500 : }
501 :
502 : // ensure relationship is different from existing relationships
503 4 : for (const auto &kv : m_osMapRelationships)
504 : {
505 2 : if (osLeftTableName == kv.second->GetLeftTableName() &&
506 1 : osRightTableName == kv.second->GetRightTableName() &&
507 3 : aosLeftTableFields == kv.second->GetLeftTableFields() &&
508 1 : aosRightTableFields == kv.second->GetRightTableFields())
509 : {
510 : failureReason =
511 1 : "A relationship between these tables and fields already exists";
512 1 : return false;
513 : }
514 : }
515 :
516 3 : return true;
517 : }
518 :
519 : /************************************************************************/
520 : /* OGRSQLiteBaseDataSource() */
521 : /************************************************************************/
522 :
523 : OGRSQLiteBaseDataSource::OGRSQLiteBaseDataSource() = default;
524 :
525 : /************************************************************************/
526 : /* ~OGRSQLiteBaseDataSource() */
527 : /************************************************************************/
528 :
529 4159 : OGRSQLiteBaseDataSource::~OGRSQLiteBaseDataSource()
530 :
531 : {
532 4159 : CloseDB();
533 :
534 4159 : FinishSpatialite();
535 :
536 4159 : if (m_bCallUndeclareFileNotToOpen)
537 : {
538 1970 : GDALOpenInfoUnDeclareFileNotToOpen(m_pszFilename);
539 : }
540 :
541 4159 : if (!m_osFinalFilename.empty())
542 : {
543 4 : if (!bSuppressOnClose)
544 : {
545 4 : CPLDebug("SQLITE", "Copying temporary file %s onto %s",
546 : m_pszFilename, m_osFinalFilename.c_str());
547 4 : if (CPLCopyFile(m_osFinalFilename.c_str(), m_pszFilename) != 0)
548 : {
549 0 : CPLError(CE_Failure, CPLE_AppDefined,
550 : "Copy temporary file %s onto %s failed", m_pszFilename,
551 : m_osFinalFilename.c_str());
552 : }
553 : }
554 4 : CPLDebug("SQLITE", "Deleting temporary file %s", m_pszFilename);
555 4 : if (VSIUnlink(m_pszFilename) != 0)
556 : {
557 0 : CPLError(CE_Failure, CPLE_AppDefined,
558 : "Deleting temporary file %s failed", m_pszFilename);
559 : }
560 : }
561 :
562 4159 : CPLFree(m_pszFilename);
563 4159 : }
564 :
565 : /************************************************************************/
566 : /* CloseDB() */
567 : /************************************************************************/
568 :
569 8330 : bool OGRSQLiteBaseDataSource::CloseDB()
570 : {
571 8330 : bool bOK = true;
572 8330 : if (hDB != nullptr)
573 : {
574 3799 : bOK = (sqlite3_close(hDB) == SQLITE_OK);
575 3799 : hDB = nullptr;
576 :
577 : // If we opened the DB in read-only mode, there might be spurious
578 : // -wal and -shm files that we can make disappear by reopening in
579 : // read-write
580 : VSIStatBufL sStat;
581 9017 : if (eAccess == GA_ReadOnly &&
582 1419 : !(STARTS_WITH(m_pszFilename, "/vsicurl/") ||
583 1415 : STARTS_WITH(m_pszFilename, "/vsitar/") ||
584 6628 : STARTS_WITH(m_pszFilename, "/vsizip/")) &&
585 1410 : VSIStatL(CPLSPrintf("%s-wal", m_pszFilename), &sStat) == 0)
586 : {
587 4 : if (sqlite3_open(m_pszFilename, &hDB) != SQLITE_OK)
588 : {
589 0 : sqlite3_close(hDB);
590 0 : hDB = nullptr;
591 : }
592 4 : else if (hDB != nullptr)
593 : {
594 : #ifdef SQLITE_FCNTL_PERSIST_WAL
595 4 : int nPersistentWAL = -1;
596 4 : sqlite3_file_control(hDB, "main", SQLITE_FCNTL_PERSIST_WAL,
597 : &nPersistentWAL);
598 4 : if (nPersistentWAL == 1)
599 : {
600 0 : nPersistentWAL = 0;
601 0 : if (sqlite3_file_control(hDB, "main",
602 : SQLITE_FCNTL_PERSIST_WAL,
603 0 : &nPersistentWAL) == SQLITE_OK)
604 : {
605 0 : CPLDebug("SQLITE",
606 : "Disabling persistent WAL succeeded");
607 : }
608 : else
609 : {
610 0 : CPLDebug("SQLITE", "Could not disable persistent WAL");
611 : }
612 : }
613 : #endif
614 :
615 : // Dummy request
616 4 : int nRowCount = 0, nColCount = 0;
617 4 : char **papszResult = nullptr;
618 4 : sqlite3_get_table(hDB, "SELECT name FROM sqlite_master WHERE 0",
619 : &papszResult, &nRowCount, &nColCount,
620 : nullptr);
621 4 : sqlite3_free_table(papszResult);
622 :
623 4 : sqlite3_close(hDB);
624 4 : hDB = nullptr;
625 : #ifdef DEBUG_VERBOSE
626 : if (VSIStatL(CPLSPrintf("%s-wal", m_pszFilename), &sStat) != 0)
627 : {
628 : CPLDebug("SQLite", "%s-wal file has been removed",
629 : m_pszFilename);
630 : }
631 : #endif
632 : }
633 : }
634 : }
635 :
636 8330 : if (pMyVFS)
637 : {
638 3078 : sqlite3_vfs_unregister(pMyVFS);
639 3078 : CPLFree(pMyVFS->pAppData);
640 3078 : CPLFree(pMyVFS);
641 3078 : pMyVFS = nullptr;
642 : }
643 :
644 8330 : return bOK;
645 : }
646 :
647 : /* Returns the first row of first column of SQL as integer */
648 76 : OGRErr OGRSQLiteBaseDataSource::PragmaCheck(const char *pszPragma,
649 : const char *pszExpected,
650 : int nRowsExpected)
651 : {
652 76 : CPLAssert(pszPragma != nullptr);
653 76 : CPLAssert(pszExpected != nullptr);
654 76 : CPLAssert(nRowsExpected >= 0);
655 :
656 76 : char **papszResult = nullptr;
657 76 : int nRowCount = 0;
658 76 : int nColCount = 0;
659 76 : char *pszErrMsg = nullptr;
660 :
661 : int rc =
662 76 : sqlite3_get_table(hDB, CPLSPrintf("PRAGMA %s", pszPragma), &papszResult,
663 : &nRowCount, &nColCount, &pszErrMsg);
664 :
665 76 : if (rc != SQLITE_OK)
666 : {
667 0 : CPLError(CE_Failure, CPLE_AppDefined, "Unable to execute PRAGMA %s: %s",
668 0 : pszPragma, pszErrMsg ? pszErrMsg : "(null)");
669 0 : sqlite3_free(pszErrMsg);
670 0 : return OGRERR_FAILURE;
671 : }
672 :
673 76 : if (nRowCount != nRowsExpected)
674 : {
675 0 : CPLError(CE_Failure, CPLE_AppDefined,
676 : "bad result for PRAGMA %s, got %d rows, expected %d",
677 : pszPragma, nRowCount, nRowsExpected);
678 0 : sqlite3_free_table(papszResult);
679 0 : return OGRERR_FAILURE;
680 : }
681 :
682 76 : if (nRowCount > 0 && !EQUAL(papszResult[1], pszExpected))
683 : {
684 0 : CPLError(CE_Failure, CPLE_AppDefined,
685 : "invalid %s (expected '%s', got '%s')", pszPragma, pszExpected,
686 0 : papszResult[1]);
687 0 : sqlite3_free_table(papszResult);
688 0 : return OGRERR_FAILURE;
689 : }
690 :
691 76 : sqlite3_free_table(papszResult);
692 :
693 76 : return OGRERR_NONE;
694 : }
695 :
696 : /************************************************************************/
697 : /* LoadRelationships() */
698 : /************************************************************************/
699 :
700 8 : void OGRSQLiteBaseDataSource::LoadRelationships() const
701 :
702 : {
703 8 : m_osMapRelationships.clear();
704 8 : LoadRelationshipsFromForeignKeys({});
705 8 : m_bHasPopulatedRelationships = true;
706 8 : }
707 :
708 : /************************************************************************/
709 : /* LoadRelationshipsFromForeignKeys() */
710 : /************************************************************************/
711 :
712 107 : void OGRSQLiteBaseDataSource::LoadRelationshipsFromForeignKeys(
713 : const std::vector<std::string> &excludedTables) const
714 :
715 : {
716 107 : if (hDB)
717 : {
718 : std::string osSQL =
719 : "SELECT m.name, p.id, p.seq, p.\"table\" AS base_table_name, "
720 : "p.\"from\", p.\"to\", "
721 : "p.on_delete FROM sqlite_master m "
722 : "JOIN pragma_foreign_key_list(m.name) p ON m.name != p.\"table\" "
723 : "WHERE m.type = 'table' "
724 : // skip over foreign keys which relate to private GPKG tables
725 : "AND base_table_name NOT LIKE 'gpkg_%' "
726 : // Same with NGA GeoInt system tables
727 : "AND base_table_name NOT LIKE 'nga_%' "
728 : // Same with Spatialite system tables
729 : "AND base_table_name NOT IN ('geometry_columns', "
730 : "'spatial_ref_sys', 'views_geometry_columns', "
731 107 : "'virts_geometry_columns') ";
732 107 : if (!excludedTables.empty())
733 : {
734 36 : std::string oExcludedTablesList;
735 93 : for (const auto &osExcludedTable : excludedTables)
736 : {
737 57 : oExcludedTablesList += !oExcludedTablesList.empty() ? "," : "";
738 : char *pszEscapedName =
739 57 : sqlite3_mprintf("'%q'", osExcludedTable.c_str());
740 57 : oExcludedTablesList += pszEscapedName;
741 57 : sqlite3_free(pszEscapedName);
742 : }
743 :
744 72 : osSQL += "AND base_table_name NOT IN (" + oExcludedTablesList +
745 : ")"
746 72 : " AND m.name NOT IN (" +
747 36 : oExcludedTablesList + ") ";
748 : }
749 107 : osSQL += "ORDER BY m.name";
750 :
751 107 : auto oResult = SQLQuery(hDB, osSQL.c_str());
752 :
753 107 : if (!oResult)
754 : {
755 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot load relationships");
756 0 : return;
757 : }
758 :
759 129 : for (int iRecord = 0; iRecord < oResult->RowCount(); iRecord++)
760 : {
761 22 : const char *pszRelatedTableName = oResult->GetValue(0, iRecord);
762 22 : if (!pszRelatedTableName)
763 0 : continue;
764 :
765 22 : const char *pszBaseTableName = oResult->GetValue(3, iRecord);
766 22 : if (!pszBaseTableName)
767 0 : continue;
768 :
769 22 : const char *pszRelatedFieldName = oResult->GetValue(4, iRecord);
770 22 : if (!pszRelatedFieldName)
771 0 : continue;
772 :
773 22 : const char *pszBaseFieldName = oResult->GetValue(5, iRecord);
774 22 : if (!pszBaseFieldName)
775 0 : continue;
776 :
777 22 : const int nId = oResult->GetValueAsInteger(1, iRecord);
778 :
779 : // form relationship name by appending foreign key id to base and
780 : // related table names
781 44 : std::ostringstream stream;
782 22 : stream << pszBaseTableName << '_' << pszRelatedTableName;
783 22 : if (nId > 0)
784 : {
785 : // note we use nId + 1 here as the first id will be zero, and
786 : // we'd like subsequent relations to have names starting with
787 : // _2, _3 etc, not _1, _2 etc.
788 2 : stream << '_' << (nId + 1);
789 : }
790 44 : const std::string osRelationName = stream.str();
791 :
792 22 : const auto it = m_osMapRelationships.find(osRelationName);
793 22 : if (it != m_osMapRelationships.end())
794 : {
795 : // already have a relationship with this name -- that means that
796 : // the base and related table name and id are the same, so we've
797 : // found a multi-column relationship
798 10 : auto osListLeftFields = it->second->GetLeftTableFields();
799 5 : osListLeftFields.emplace_back(pszBaseFieldName);
800 5 : it->second->SetLeftTableFields(osListLeftFields);
801 :
802 10 : auto osListRightFields = it->second->GetRightTableFields();
803 5 : osListRightFields.emplace_back(pszRelatedFieldName);
804 5 : it->second->SetRightTableFields(osListRightFields);
805 : }
806 : else
807 : {
808 : std::unique_ptr<GDALRelationship> poRelationship(
809 : new GDALRelationship(osRelationName, pszBaseTableName,
810 51 : pszRelatedTableName, GRC_ONE_TO_MANY));
811 34 : poRelationship->SetLeftTableFields({pszBaseFieldName});
812 34 : poRelationship->SetRightTableFields({pszRelatedFieldName});
813 17 : poRelationship->SetRelatedTableType("features");
814 :
815 17 : if (const char *pszOnDeleteAction =
816 17 : oResult->GetValue(6, iRecord))
817 : {
818 17 : if (EQUAL(pszOnDeleteAction, "CASCADE"))
819 : {
820 2 : poRelationship->SetType(GRT_COMPOSITE);
821 : }
822 : }
823 :
824 17 : m_osMapRelationships[osRelationName] =
825 34 : std::move(poRelationship);
826 : }
827 : }
828 : }
829 : }
830 :
831 : /************************************************************************/
832 : /* GetRelationshipNames() */
833 : /************************************************************************/
834 :
835 90 : std::vector<std::string> OGRSQLiteBaseDataSource::GetRelationshipNames(
836 : CPL_UNUSED CSLConstList papszOptions) const
837 :
838 : {
839 90 : if (!m_bHasPopulatedRelationships)
840 : {
841 75 : LoadRelationships();
842 : }
843 :
844 90 : std::vector<std::string> oasNames;
845 90 : oasNames.reserve(m_osMapRelationships.size());
846 142 : for (const auto &kv : m_osMapRelationships)
847 : {
848 52 : oasNames.emplace_back(kv.first);
849 : }
850 90 : return oasNames;
851 : }
852 :
853 : /************************************************************************/
854 : /* GetRelationship() */
855 : /************************************************************************/
856 :
857 : const GDALRelationship *
858 79 : OGRSQLiteBaseDataSource::GetRelationship(const std::string &name) const
859 :
860 : {
861 79 : if (!m_bHasPopulatedRelationships)
862 : {
863 9 : LoadRelationships();
864 : }
865 :
866 79 : const auto it = m_osMapRelationships.find(name);
867 79 : if (it == m_osMapRelationships.end())
868 37 : return nullptr;
869 :
870 42 : return it->second.get();
871 : }
872 :
873 : /************************************************************************/
874 : /* prepareSql() */
875 : /************************************************************************/
876 :
877 12199 : sqlite3_stmt *OGRSQLiteBaseDataSource::prepareSql(sqlite3 *db, const char *zSql,
878 : int nByte)
879 : {
880 12199 : sqlite3_stmt *stmt = nullptr;
881 12199 : const char *pszTail = nullptr;
882 12199 : const int rc = sqlite3_prepare_v2(db, zSql, nByte, &stmt, &pszTail);
883 12199 : if (rc != SQLITE_OK && pfnQueryLoggerFunc)
884 : {
885 1 : pfnQueryLoggerFunc(
886 : zSql,
887 2 : SQLFormatErrorMsgFailedPrepare(db, "Error preparing query: ", zSql)
888 : .c_str(),
889 : -1, -1, poQueryLoggerArg);
890 : }
891 12198 : else if (strchr(zSql, ';') && pszTail && SQLHasRemainingContent(pszTail))
892 : {
893 6 : sqlite3_finalize(stmt);
894 6 : stmt = nullptr;
895 : }
896 12199 : return stmt;
897 : }
898 :
899 : /************************************************************************/
900 : /* OGRSQLiteDataSource() */
901 : /************************************************************************/
902 :
903 : OGRSQLiteDataSource::OGRSQLiteDataSource() = default;
904 :
905 : /************************************************************************/
906 : /* ~OGRSQLiteDataSource() */
907 : /************************************************************************/
908 :
909 2660 : OGRSQLiteDataSource::~OGRSQLiteDataSource()
910 :
911 : {
912 1330 : OGRSQLiteDataSource::Close();
913 2660 : }
914 :
915 : /************************************************************************/
916 : /* Close() */
917 : /************************************************************************/
918 :
919 1891 : CPLErr OGRSQLiteDataSource::Close(GDALProgressFunc, void *)
920 : {
921 1891 : CPLErr eErr = CE_None;
922 1891 : if (nOpenFlags != OPEN_FLAGS_CLOSED)
923 : {
924 1330 : if (OGRSQLiteDataSource::FlushCache(true) != CE_None)
925 0 : eErr = CE_Failure;
926 :
927 : #ifdef HAVE_RASTERLITE2
928 : if (m_pRL2Coverage != nullptr)
929 : {
930 : rl2_destroy_coverage(m_pRL2Coverage);
931 : }
932 : #endif
933 1330 : for (size_t i = 0; i < m_apoOverviewDS.size(); ++i)
934 : {
935 0 : delete m_apoOverviewDS[i];
936 : }
937 :
938 1330 : if (!m_apoLayers.empty() || !m_apoInvisibleLayers.empty())
939 : {
940 : // Close any remaining iterator
941 2188 : for (auto &poLayer : m_apoLayers)
942 1373 : poLayer->ResetReading();
943 817 : for (auto &poLayer : m_apoInvisibleLayers)
944 2 : poLayer->ResetReading();
945 :
946 815 : if (!IsMarkedSuppressOnClose())
947 : {
948 : // Create spatial indices in a transaction for faster execution
949 812 : if (hDB)
950 812 : SoftStartTransaction();
951 2181 : for (auto &poLayer : m_apoLayers)
952 : {
953 1369 : if (poLayer->IsTableLayer())
954 : {
955 : OGRSQLiteTableLayer *poTableLayer =
956 1364 : cpl::down_cast<OGRSQLiteTableLayer *>(
957 : poLayer.get());
958 1364 : poTableLayer->RunDeferredCreationIfNecessary();
959 1364 : poTableLayer->CreateSpatialIndexIfNecessary();
960 : }
961 : }
962 812 : if (hDB)
963 812 : SoftCommitTransaction();
964 : }
965 : }
966 :
967 1330 : if (!IsMarkedSuppressOnClose())
968 1327 : SaveStatistics();
969 :
970 1330 : m_apoLayers.clear();
971 1330 : m_apoInvisibleLayers.clear();
972 :
973 1330 : m_oSRSCache.clear();
974 :
975 1330 : if (!CloseDB())
976 1 : eErr = CE_Failure;
977 : #ifdef HAVE_RASTERLITE2
978 : FinishRasterLite2();
979 : #endif
980 :
981 1330 : if (GDALPamDataset::Close() != CE_None)
982 0 : eErr = CE_Failure;
983 : }
984 1891 : return eErr;
985 : }
986 :
987 : #ifdef HAVE_RASTERLITE2
988 :
989 : /************************************************************************/
990 : /* InitRasterLite2() */
991 : /************************************************************************/
992 :
993 : bool OGRSQLiteDataSource::InitRasterLite2()
994 : {
995 : CPLAssert(m_hRL2Ctxt == nullptr);
996 : m_hRL2Ctxt = rl2_alloc_private();
997 : if (m_hRL2Ctxt != nullptr)
998 : {
999 : rl2_init(hDB, m_hRL2Ctxt, 0);
1000 : }
1001 : return m_hRL2Ctxt != nullptr;
1002 : }
1003 :
1004 : /************************************************************************/
1005 : /* FinishRasterLite2() */
1006 : /************************************************************************/
1007 :
1008 : void OGRSQLiteDataSource::FinishRasterLite2()
1009 : {
1010 : if (m_hRL2Ctxt != nullptr)
1011 : {
1012 : rl2_cleanup_private(m_hRL2Ctxt);
1013 : m_hRL2Ctxt = nullptr;
1014 : }
1015 : }
1016 :
1017 : #endif // HAVE_RASTERLITE2
1018 :
1019 : /************************************************************************/
1020 : /* SaveStatistics() */
1021 : /************************************************************************/
1022 :
1023 1327 : void OGRSQLiteDataSource::SaveStatistics()
1024 : {
1025 651 : if (!m_bIsSpatiaLiteDB || !IsSpatialiteLoaded() ||
1026 1978 : m_bLastSQLCommandIsUpdateLayerStatistics || !GetUpdate())
1027 719 : return;
1028 :
1029 608 : int nSavedAllLayersCacheData = -1;
1030 :
1031 948 : for (auto &poLayer : m_apoLayers)
1032 : {
1033 340 : if (poLayer->IsTableLayer())
1034 : {
1035 : OGRSQLiteTableLayer *poTableLayer =
1036 339 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
1037 339 : int nSaveRet = poTableLayer->SaveStatistics();
1038 339 : if (nSaveRet >= 0)
1039 : {
1040 134 : if (nSavedAllLayersCacheData < 0)
1041 39 : nSavedAllLayersCacheData = nSaveRet;
1042 : else
1043 95 : nSavedAllLayersCacheData &= nSaveRet;
1044 : }
1045 : }
1046 : }
1047 :
1048 608 : if (hDB && nSavedAllLayersCacheData == TRUE)
1049 : {
1050 39 : int nReplaceEventId = -1;
1051 :
1052 : auto oResult = SQLQuery(
1053 : hDB, "SELECT event_id, table_name, geometry_column, event "
1054 78 : "FROM spatialite_history ORDER BY event_id DESC LIMIT 1");
1055 :
1056 39 : if (oResult && oResult->RowCount() == 1)
1057 : {
1058 39 : const char *pszEventId = oResult->GetValue(0, 0);
1059 39 : const char *pszTableName = oResult->GetValue(1, 0);
1060 39 : const char *pszGeomCol = oResult->GetValue(2, 0);
1061 39 : const char *pszEvent = oResult->GetValue(3, 0);
1062 :
1063 39 : if (pszEventId != nullptr && pszTableName != nullptr &&
1064 39 : pszGeomCol != nullptr && pszEvent != nullptr &&
1065 39 : strcmp(pszTableName, "ALL-TABLES") == 0 &&
1066 3 : strcmp(pszGeomCol, "ALL-GEOMETRY-COLUMNS") == 0 &&
1067 3 : strcmp(pszEvent, "UpdateLayerStatistics") == 0)
1068 : {
1069 3 : nReplaceEventId = atoi(pszEventId);
1070 : }
1071 : }
1072 :
1073 39 : const char *pszNow = HasSpatialite4Layout()
1074 39 : ? "strftime('%Y-%m-%dT%H:%M:%fZ','now')"
1075 39 : : "DateTime('now')";
1076 : const char *pszSQL;
1077 39 : if (nReplaceEventId >= 0)
1078 : {
1079 3 : pszSQL = CPLSPrintf("UPDATE spatialite_history SET "
1080 : "timestamp = %s "
1081 : "WHERE event_id = %d",
1082 : pszNow, nReplaceEventId);
1083 : }
1084 : else
1085 : {
1086 36 : pszSQL = CPLSPrintf(
1087 : "INSERT INTO spatialite_history (table_name, geometry_column, "
1088 : "event, timestamp, ver_sqlite, ver_splite) VALUES ("
1089 : "'ALL-TABLES', 'ALL-GEOMETRY-COLUMNS', "
1090 : "'UpdateLayerStatistics', "
1091 : "%s, sqlite_version(), spatialite_version())",
1092 : pszNow);
1093 : }
1094 :
1095 39 : SQLCommand(hDB, pszSQL);
1096 : }
1097 : }
1098 :
1099 : /************************************************************************/
1100 : /* SetSynchronous() */
1101 : /************************************************************************/
1102 :
1103 3789 : bool OGRSQLiteBaseDataSource::SetSynchronous()
1104 : {
1105 : const char *pszSqliteSync =
1106 3789 : CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", nullptr);
1107 3789 : if (pszSqliteSync != nullptr)
1108 : {
1109 1583 : const char *pszSQL = nullptr;
1110 1583 : if (EQUAL(pszSqliteSync, "OFF") || EQUAL(pszSqliteSync, "0") ||
1111 0 : EQUAL(pszSqliteSync, "FALSE"))
1112 1583 : pszSQL = "PRAGMA synchronous = OFF";
1113 0 : else if (EQUAL(pszSqliteSync, "NORMAL") || EQUAL(pszSqliteSync, "1"))
1114 0 : pszSQL = "PRAGMA synchronous = NORMAL";
1115 0 : else if (EQUAL(pszSqliteSync, "ON") || EQUAL(pszSqliteSync, "FULL") ||
1116 0 : EQUAL(pszSqliteSync, "2") || EQUAL(pszSqliteSync, "TRUE"))
1117 0 : pszSQL = "PRAGMA synchronous = FULL";
1118 : else
1119 0 : CPLError(CE_Warning, CPLE_AppDefined,
1120 : "Unrecognized value for OGR_SQLITE_SYNCHRONOUS : %s",
1121 : pszSqliteSync);
1122 :
1123 1583 : return pszSQL != nullptr && SQLCommand(hDB, pszSQL) == OGRERR_NONE;
1124 : }
1125 2206 : return true;
1126 : }
1127 :
1128 : /************************************************************************/
1129 : /* LoadExtensions() */
1130 : /************************************************************************/
1131 :
1132 3789 : void OGRSQLiteBaseDataSource::LoadExtensions()
1133 : {
1134 : const char *pszExtensions =
1135 3789 : CPLGetConfigOption("OGR_SQLITE_LOAD_EXTENSIONS", nullptr);
1136 3789 : if (pszExtensions != nullptr)
1137 : {
1138 : #ifdef OGR_SQLITE_ALLOW_LOAD_EXTENSIONS
1139 : // Allow sqlite3_load_extension() (C API only)
1140 : #ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
1141 4 : int oldMode = 0;
1142 4 : if (sqlite3_db_config(hDB, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, -1,
1143 4 : &oldMode) != SQLITE_OK)
1144 : {
1145 0 : CPLError(CE_Failure, CPLE_AppDefined,
1146 : "Cannot get initial value for "
1147 : "SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION");
1148 0 : return;
1149 : }
1150 4 : CPLDebugOnly(
1151 : "SQLite",
1152 : "Initial mode for SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION = %d",
1153 : oldMode);
1154 4 : int newMode = 0;
1155 8 : if (oldMode != 1 &&
1156 4 : (sqlite3_db_config(hDB, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1,
1157 4 : &newMode) != SQLITE_OK ||
1158 4 : newMode != 1))
1159 : {
1160 0 : CPLError(CE_Failure, CPLE_AppDefined,
1161 : "SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION failed");
1162 0 : return;
1163 : }
1164 : #endif
1165 : const CPLStringList aosExtensions(
1166 8 : CSLTokenizeString2(pszExtensions, ",", 0));
1167 4 : bool bRestoreOldMode = true;
1168 8 : for (int i = 0; i < aosExtensions.size(); i++)
1169 : {
1170 4 : if (EQUAL(aosExtensions[i], "ENABLE_SQL_LOAD_EXTENSION"))
1171 : {
1172 2 : if (sqlite3_enable_load_extension(hDB, 1) == SQLITE_OK)
1173 : {
1174 2 : bRestoreOldMode = false;
1175 : }
1176 : else
1177 : {
1178 0 : CPLError(CE_Failure, CPLE_AppDefined,
1179 : "sqlite3_enable_load_extension() failed");
1180 : }
1181 : }
1182 : else
1183 : {
1184 2 : char *pszErrMsg = nullptr;
1185 2 : if (sqlite3_load_extension(hDB, aosExtensions[i], nullptr,
1186 2 : &pszErrMsg) != SQLITE_OK)
1187 : {
1188 1 : CPLError(CE_Failure, CPLE_AppDefined,
1189 : "Cannot load extension %s: %s", aosExtensions[i],
1190 1 : pszErrMsg ? pszErrMsg : "unknown reason");
1191 : }
1192 2 : sqlite3_free(pszErrMsg);
1193 : }
1194 : }
1195 4 : CPL_IGNORE_RET_VAL(bRestoreOldMode);
1196 : #ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
1197 4 : if (bRestoreOldMode && oldMode != 1)
1198 : {
1199 2 : CPL_IGNORE_RET_VAL(sqlite3_db_config(
1200 : hDB, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, oldMode, nullptr));
1201 : }
1202 : #endif
1203 : #else
1204 : CPLError(
1205 : CE_Failure, CPLE_NotSupported,
1206 : "The OGR_SQLITE_LOAD_EXTENSIONS was specified at run time, "
1207 : "but GDAL has been built without OGR_SQLITE_ALLOW_LOAD_EXTENSIONS. "
1208 : "So extensions won't be loaded");
1209 : #endif
1210 : }
1211 : }
1212 :
1213 : /************************************************************************/
1214 : /* SetCacheSize() */
1215 : /************************************************************************/
1216 :
1217 3789 : bool OGRSQLiteBaseDataSource::SetCacheSize()
1218 : {
1219 : const char *pszSqliteCacheMB =
1220 3789 : CPLGetConfigOption("OGR_SQLITE_CACHE", nullptr);
1221 3789 : if (pszSqliteCacheMB != nullptr)
1222 : {
1223 0 : const GIntBig iSqliteCacheBytes =
1224 0 : static_cast<GIntBig>(atoi(pszSqliteCacheMB)) * 1024 * 1024;
1225 :
1226 : /* querying the current PageSize */
1227 0 : int iSqlitePageSize = SQLGetInteger(hDB, "PRAGMA page_size", nullptr);
1228 0 : if (iSqlitePageSize <= 0)
1229 0 : return false;
1230 : /* computing the CacheSize as #Pages */
1231 0 : const int iSqliteCachePages =
1232 0 : static_cast<int>(iSqliteCacheBytes / iSqlitePageSize);
1233 0 : if (iSqliteCachePages <= 0)
1234 0 : return false;
1235 :
1236 0 : return SQLCommand(hDB, CPLSPrintf("PRAGMA cache_size = %d",
1237 0 : iSqliteCachePages)) == OGRERR_NONE;
1238 : }
1239 3789 : return true;
1240 : }
1241 :
1242 : /************************************************************************/
1243 : /* OGRSQLiteBaseDataSourceNotifyFileOpened() */
1244 : /************************************************************************/
1245 :
1246 24690 : static void OGRSQLiteBaseDataSourceNotifyFileOpened(void *pfnUserData,
1247 : const char *pszFilename,
1248 : VSILFILE *fp)
1249 : {
1250 : static_cast<OGRSQLiteBaseDataSource *>(pfnUserData)
1251 24690 : ->NotifyFileOpened(pszFilename, fp);
1252 24690 : }
1253 :
1254 : /************************************************************************/
1255 : /* NotifyFileOpened() */
1256 : /************************************************************************/
1257 :
1258 24690 : void OGRSQLiteBaseDataSource::NotifyFileOpened(const char *pszFilename,
1259 : VSILFILE *fp)
1260 : {
1261 24690 : if (strcmp(pszFilename, m_pszFilename) == 0)
1262 : {
1263 3078 : fpMainFile = fp;
1264 : }
1265 24690 : }
1266 :
1267 : #ifdef USE_SQLITE_DEBUG_MEMALLOC
1268 :
1269 : /* DMA9 */
1270 : constexpr int DMA_SIGNATURE = 0x444D4139;
1271 :
1272 : static void *OGRSQLiteDMA_Malloc(int size)
1273 : {
1274 : int *ret = (int *)CPLMalloc(size + 8);
1275 : ret[0] = size;
1276 : ret[1] = DMA_SIGNATURE;
1277 : return ret + 2;
1278 : }
1279 :
1280 : static void *OGRSQLiteDMA_Realloc(void *old_ptr, int size)
1281 : {
1282 : CPLAssert(((int *)old_ptr)[-1] == DMA_SIGNATURE);
1283 : int *ret = (int *)CPLRealloc(old_ptr ? (int *)old_ptr - 2 : NULL, size + 8);
1284 : ret[0] = size;
1285 : ret[1] = DMA_SIGNATURE;
1286 : return ret + 2;
1287 : }
1288 :
1289 : static void OGRSQLiteDMA_Free(void *ptr)
1290 : {
1291 : if (ptr)
1292 : {
1293 : CPLAssert(((int *)ptr)[-1] == DMA_SIGNATURE);
1294 : ((int *)ptr)[-1] = 0;
1295 : CPLFree((int *)ptr - 2);
1296 : }
1297 : }
1298 :
1299 : static int OGRSQLiteDMA_Size(void *ptr)
1300 : {
1301 : if (ptr)
1302 : {
1303 : CPLAssert(((int *)ptr)[-1] == DMA_SIGNATURE);
1304 : return ((int *)ptr)[-2];
1305 : }
1306 : else
1307 : return 0;
1308 : }
1309 :
1310 : static int OGRSQLiteDMA_Roundup(int size)
1311 : {
1312 : return (size + 7) & (~7);
1313 : }
1314 :
1315 : static int OGRSQLiteDMA_Init(void *)
1316 : {
1317 : return SQLITE_OK;
1318 : }
1319 :
1320 : static void OGRSQLiteDMA_Shutdown(void *)
1321 : {
1322 : }
1323 :
1324 : const struct sqlite3_mem_methods sDebugMemAlloc = {
1325 : OGRSQLiteDMA_Malloc, OGRSQLiteDMA_Free,
1326 : OGRSQLiteDMA_Realloc, OGRSQLiteDMA_Size,
1327 : OGRSQLiteDMA_Roundup, OGRSQLiteDMA_Init,
1328 : OGRSQLiteDMA_Shutdown, NULL};
1329 :
1330 : #endif // USE_SQLITE_DEBUG_MEMALLOC
1331 :
1332 : /************************************************************************/
1333 : /* OpenOrCreateDB() */
1334 : /************************************************************************/
1335 :
1336 3804 : bool OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn,
1337 : bool bRegisterOGR2SQLiteExtensions,
1338 : bool bLoadExtensions)
1339 : {
1340 : #ifdef USE_SQLITE_DEBUG_MEMALLOC
1341 : if (CPLTestBool(CPLGetConfigOption("USE_SQLITE_DEBUG_MEMALLOC", "NO")))
1342 : sqlite3_config(SQLITE_CONFIG_MALLOC, &sDebugMemAlloc);
1343 : #endif
1344 :
1345 3804 : if (bRegisterOGR2SQLiteExtensions)
1346 1329 : OGR2SQLITE_Register();
1347 :
1348 : const bool bUseOGRVFS =
1349 3804 : CPLTestBool(CPLGetConfigOption("SQLITE_USE_OGR_VFS", "NO")) ||
1350 4529 : STARTS_WITH(m_pszFilename, "/vsi") ||
1351 : // https://sqlite.org/forum/forumpost/0b1b8b5116: MAX_PATHNAME=512
1352 725 : strlen(m_pszFilename) >= 512 - strlen(".journal");
1353 :
1354 : #ifdef SQLITE_OPEN_URI
1355 : const bool bNoLock =
1356 3804 : CPLTestBool(CSLFetchNameValueDef(papszOpenOptions, "NOLOCK", "NO"));
1357 3804 : const char *pszImmutable = CSLFetchNameValue(papszOpenOptions, "IMMUTABLE");
1358 3804 : const bool bImmutable = pszImmutable && CPLTestBool(pszImmutable);
1359 3804 : if (m_osFilenameForSQLiteOpen.empty() &&
1360 3793 : (flagsIn & SQLITE_OPEN_READWRITE) == 0 &&
1361 7597 : !STARTS_WITH(m_pszFilename, "file:") && (bNoLock || bImmutable))
1362 : {
1363 7 : m_osFilenameForSQLiteOpen = "file:";
1364 :
1365 : // Apply rules from "3.1. The URI Path" of
1366 : // https://www.sqlite.org/uri.html
1367 14 : CPLString osFilenameForURI(m_pszFilename);
1368 7 : osFilenameForURI.replaceAll('?', "%3f");
1369 7 : osFilenameForURI.replaceAll('#', "%23");
1370 : #ifdef _WIN32
1371 : osFilenameForURI.replaceAll('\\', '/');
1372 : #endif
1373 7 : if (!STARTS_WITH(m_pszFilename, "/vsi"))
1374 : {
1375 5 : osFilenameForURI.replaceAll("//", '/');
1376 : }
1377 : #ifdef _WIN32
1378 : if (osFilenameForURI.size() > 3 && osFilenameForURI[1] == ':' &&
1379 : osFilenameForURI[2] == '/')
1380 : {
1381 : osFilenameForURI = '/' + osFilenameForURI;
1382 : }
1383 : #endif
1384 :
1385 7 : m_osFilenameForSQLiteOpen += osFilenameForURI;
1386 7 : m_osFilenameForSQLiteOpen += "?";
1387 7 : if (bNoLock)
1388 5 : m_osFilenameForSQLiteOpen += "nolock=1";
1389 7 : if (bImmutable)
1390 : {
1391 2 : if (m_osFilenameForSQLiteOpen.back() != '?')
1392 0 : m_osFilenameForSQLiteOpen += '&';
1393 2 : m_osFilenameForSQLiteOpen += "immutable=1";
1394 : }
1395 : }
1396 : #endif
1397 3804 : if (m_osFilenameForSQLiteOpen.empty())
1398 : {
1399 3786 : m_osFilenameForSQLiteOpen = m_pszFilename;
1400 : }
1401 :
1402 : // No mutex since OGR objects are not supposed to be used concurrently
1403 : // from multiple threads.
1404 3804 : int flags = flagsIn | SQLITE_OPEN_NOMUTEX;
1405 : #ifdef SQLITE_OPEN_URI
1406 : // This code enables support for named memory databases in SQLite.
1407 : // SQLITE_USE_URI is checked only to enable backward compatibility, in
1408 : // case we accidentally hijacked some other format.
1409 3812 : if (STARTS_WITH(m_osFilenameForSQLiteOpen.c_str(), "file:") &&
1410 8 : CPLTestBool(CPLGetConfigOption("SQLITE_USE_URI", "YES")))
1411 : {
1412 8 : flags |= SQLITE_OPEN_URI;
1413 : }
1414 : #endif
1415 :
1416 3804 : bool bPageSizeFound = false;
1417 3804 : bool bSecureDeleteFound = false;
1418 :
1419 : const char *pszSqlitePragma =
1420 3804 : CPLGetConfigOption("OGR_SQLITE_PRAGMA", nullptr);
1421 7608 : CPLString osJournalMode = CPLGetConfigOption("OGR_SQLITE_JOURNAL", "");
1422 :
1423 3804 : if (bUseOGRVFS)
1424 : {
1425 3079 : pMyVFS =
1426 3079 : OGRSQLiteCreateVFS(OGRSQLiteBaseDataSourceNotifyFileOpened, this);
1427 3079 : sqlite3_vfs_register(pMyVFS, 0);
1428 : }
1429 :
1430 3805 : for (int iterOpen = 0; iterOpen < 2; iterOpen++)
1431 : {
1432 3805 : CPLAssert(hDB == nullptr);
1433 3805 : int rc = sqlite3_open_v2(m_osFilenameForSQLiteOpen.c_str(), &hDB, flags,
1434 3805 : pMyVFS ? pMyVFS->zName : nullptr);
1435 3805 : if (rc != SQLITE_OK || !hDB)
1436 : {
1437 11 : CPLError(CE_Failure, CPLE_OpenFailed, "sqlite3_open(%s) failed: %s",
1438 : m_pszFilename,
1439 11 : hDB ? sqlite3_errmsg(hDB) : "(unknown error)");
1440 11 : sqlite3_close(hDB);
1441 11 : hDB = nullptr;
1442 11 : return false;
1443 : }
1444 :
1445 : #ifdef SQLITE_DBCONFIG_DEFENSIVE
1446 : // SQLite builds on recent MacOS enable defensive mode by default, which
1447 : // causes issues in the VDV driver (when updating a deleted database),
1448 : // or in the GPKG driver (when modifying a CREATE TABLE DDL with
1449 : // writable_schema=ON) So disable it.
1450 3794 : int bDefensiveOldValue = 0;
1451 3794 : if (sqlite3_db_config(hDB, SQLITE_DBCONFIG_DEFENSIVE, -1,
1452 7588 : &bDefensiveOldValue) == SQLITE_OK &&
1453 3794 : bDefensiveOldValue == 1)
1454 : {
1455 0 : if (sqlite3_db_config(hDB, SQLITE_DBCONFIG_DEFENSIVE, 0, nullptr) ==
1456 : SQLITE_OK)
1457 : {
1458 0 : CPLDebug("SQLITE", "Disabling defensive mode succeeded");
1459 : }
1460 : else
1461 : {
1462 0 : CPLDebug("SQLITE", "Could not disable defensive mode");
1463 : }
1464 : }
1465 : #endif
1466 :
1467 : #ifdef SQLITE_FCNTL_PERSIST_WAL
1468 3794 : int nPersistentWAL = -1;
1469 3794 : sqlite3_file_control(hDB, "main", SQLITE_FCNTL_PERSIST_WAL,
1470 : &nPersistentWAL);
1471 3794 : if (nPersistentWAL == 1)
1472 : {
1473 0 : nPersistentWAL = 0;
1474 0 : if (sqlite3_file_control(hDB, "main", SQLITE_FCNTL_PERSIST_WAL,
1475 0 : &nPersistentWAL) == SQLITE_OK)
1476 : {
1477 0 : CPLDebug("SQLITE", "Disabling persistent WAL succeeded");
1478 : }
1479 : else
1480 : {
1481 0 : CPLDebug("SQLITE", "Could not disable persistent WAL");
1482 : }
1483 : }
1484 : #endif
1485 :
1486 3794 : if (pszSqlitePragma != nullptr)
1487 : {
1488 : char **papszTokens =
1489 6 : CSLTokenizeString2(pszSqlitePragma, ",", CSLT_HONOURSTRINGS);
1490 12 : for (int i = 0; papszTokens[i] != nullptr; i++)
1491 : {
1492 6 : if (STARTS_WITH_CI(papszTokens[i], "PAGE_SIZE"))
1493 0 : bPageSizeFound = true;
1494 6 : else if (STARTS_WITH_CI(papszTokens[i], "JOURNAL_MODE"))
1495 : {
1496 0 : const char *pszEqual = strchr(papszTokens[i], '=');
1497 0 : if (pszEqual)
1498 : {
1499 0 : osJournalMode = pszEqual + 1;
1500 0 : osJournalMode.Trim();
1501 : // Only apply journal_mode after changing page_size
1502 0 : continue;
1503 : }
1504 : }
1505 6 : else if (STARTS_WITH_CI(papszTokens[i], "SECURE_DELETE"))
1506 1 : bSecureDeleteFound = true;
1507 :
1508 6 : const char *pszSQL = CPLSPrintf("PRAGMA %s", papszTokens[i]);
1509 :
1510 6 : CPL_IGNORE_RET_VAL(
1511 6 : sqlite3_exec(hDB, pszSQL, nullptr, nullptr, nullptr));
1512 : }
1513 6 : CSLDestroy(papszTokens);
1514 : }
1515 :
1516 3794 : const char *pszVal = CPLGetConfigOption("SQLITE_BUSY_TIMEOUT", "5000");
1517 3794 : if (pszVal != nullptr)
1518 : {
1519 3794 : sqlite3_busy_timeout(hDB, atoi(pszVal));
1520 : }
1521 :
1522 : #ifdef SQLITE_OPEN_URI
1523 3794 : if (iterOpen == 0 && bNoLock && !bImmutable)
1524 : {
1525 6 : int nRowCount = 0, nColCount = 0;
1526 6 : char **papszResult = nullptr;
1527 6 : rc = sqlite3_get_table(hDB, "PRAGMA journal_mode", &papszResult,
1528 : &nRowCount, &nColCount, nullptr);
1529 6 : bool bWal = false;
1530 : // rc == SQLITE_CANTOPEN seems to be what we get when issuing the
1531 : // above in nolock mode on a wal enabled file
1532 6 : if (rc != SQLITE_OK ||
1533 5 : (nRowCount == 1 && nColCount == 1 && papszResult[1] &&
1534 5 : EQUAL(papszResult[1], "wal")))
1535 : {
1536 1 : bWal = true;
1537 : }
1538 6 : sqlite3_free_table(papszResult);
1539 6 : if (bWal)
1540 : {
1541 1 : flags &= ~SQLITE_OPEN_URI;
1542 1 : sqlite3_close(hDB);
1543 1 : hDB = nullptr;
1544 1 : CPLDebug("SQLite",
1545 : "Cannot open %s in nolock mode because it is "
1546 : "presumably in -wal mode",
1547 : m_pszFilename);
1548 1 : m_osFilenameForSQLiteOpen = m_pszFilename;
1549 1 : continue;
1550 : }
1551 : }
1552 : #endif
1553 3793 : break;
1554 : }
1555 :
1556 3793 : if ((flagsIn & SQLITE_OPEN_CREATE) == 0)
1557 : {
1558 2392 : if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_READ", "NO")))
1559 : {
1560 1 : if (SQLGetInteger(hDB,
1561 : "SELECT 1 FROM sqlite_master "
1562 : "WHERE type = 'table' AND name = 'vfk_tables'",
1563 1 : nullptr))
1564 4 : return false; /* DB is valid VFK datasource */
1565 : }
1566 :
1567 2391 : int nRowCount = 0, nColCount = 0;
1568 2391 : char **papszResult = nullptr;
1569 2391 : char *pszErrMsg = nullptr;
1570 : int rc =
1571 2391 : sqlite3_get_table(hDB,
1572 : "SELECT 1 FROM sqlite_master "
1573 : "WHERE (type = 'trigger' OR type = 'view') AND ("
1574 : "sql LIKE '%%ogr_geocode%%' OR "
1575 : "sql LIKE '%%ogr_datasource_load_layers%%' OR "
1576 : "sql LIKE '%%ogr_GetConfigOption%%' OR "
1577 : "sql LIKE '%%ogr_SetConfigOption%%' ) "
1578 : "LIMIT 1",
1579 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
1580 2391 : if (rc != SQLITE_OK)
1581 : {
1582 3 : bool bIsWAL = false;
1583 3 : VSILFILE *fp = VSIFOpenL(m_pszFilename, "rb");
1584 3 : if (fp != nullptr)
1585 : {
1586 3 : GByte byVal = 0;
1587 3 : VSIFSeekL(fp, 18, SEEK_SET);
1588 3 : VSIFReadL(&byVal, 1, 1, fp);
1589 3 : bIsWAL = byVal == 2;
1590 3 : VSIFCloseL(fp);
1591 : }
1592 3 : if (bIsWAL)
1593 : {
1594 : #ifdef SQLITE_OPEN_URI
1595 5 : if (pszImmutable == nullptr &&
1596 4 : (flags & SQLITE_OPEN_READONLY) != 0 &&
1597 1 : m_osFilenameForSQLiteOpen == m_pszFilename)
1598 : {
1599 1 : CPLError(CE_Warning, CPLE_AppDefined,
1600 : "%s: this file is a WAL-enabled database. "
1601 : "It cannot be opened "
1602 : "because it is presumably read-only or in a "
1603 : "read-only directory. Retrying with IMMUTABLE=YES "
1604 : "open option",
1605 : pszErrMsg);
1606 1 : sqlite3_free(pszErrMsg);
1607 1 : CloseDB();
1608 1 : m_osFilenameForSQLiteOpen.clear();
1609 1 : papszOpenOptions =
1610 1 : CSLSetNameValue(papszOpenOptions, "IMMUTABLE", "YES");
1611 1 : return OpenOrCreateDB(flagsIn,
1612 : bRegisterOGR2SQLiteExtensions,
1613 1 : bLoadExtensions);
1614 : }
1615 : #endif
1616 :
1617 2 : CPLError(CE_Failure, CPLE_AppDefined,
1618 : "%s: this file is a WAL-enabled database. "
1619 : "It cannot be opened "
1620 : "because it is presumably read-only or in a "
1621 : "read-only directory.%s",
1622 : pszErrMsg,
1623 : #ifdef SQLITE_OPEN_URI
1624 : pszImmutable != nullptr
1625 : ? ""
1626 : : " Try opening with IMMUTABLE=YES open option"
1627 : #else
1628 : ""
1629 : #endif
1630 : );
1631 : }
1632 : else
1633 : {
1634 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrMsg);
1635 : }
1636 2 : sqlite3_free(pszErrMsg);
1637 2 : return false;
1638 : }
1639 :
1640 2388 : sqlite3_free_table(papszResult);
1641 :
1642 2388 : if (nRowCount > 0)
1643 : {
1644 0 : if (!CPLTestBool(CPLGetConfigOption(
1645 : "ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW", "NO")))
1646 : {
1647 0 : CPLError(CE_Failure, CPLE_OpenFailed, "%s",
1648 : "A trigger and/or view calls a OGR extension SQL "
1649 : "function that could be used to "
1650 : "steal data, or use network bandwidth, without your "
1651 : "consent.\n"
1652 : "The database will not be opened unless the "
1653 : "ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW "
1654 : "configuration option to YES.");
1655 0 : return false;
1656 : }
1657 : }
1658 : }
1659 :
1660 3797 : if (m_osFilenameForSQLiteOpen != m_pszFilename &&
1661 8 : (m_osFilenameForSQLiteOpen.find("?nolock=1") != std::string::npos ||
1662 2 : m_osFilenameForSQLiteOpen.find("&nolock=1") != std::string::npos))
1663 : {
1664 4 : m_bNoLock = true;
1665 4 : CPLDebug("SQLite", "%s open in nolock mode", m_pszFilename);
1666 : }
1667 :
1668 3789 : if (!bPageSizeFound && (flagsIn & SQLITE_OPEN_CREATE) != 0)
1669 : {
1670 : // Since sqlite 3.12 the default page_size is now 4096. But we
1671 : // can use that even with older versions.
1672 1401 : CPL_IGNORE_RET_VAL(sqlite3_exec(hDB, "PRAGMA page_size = 4096", nullptr,
1673 : nullptr, nullptr));
1674 : }
1675 :
1676 : // journal_mode = WAL must be done *AFTER* changing page size.
1677 3789 : if (!osJournalMode.empty())
1678 : {
1679 : const char *pszSQL =
1680 2 : CPLSPrintf("PRAGMA journal_mode = %s", osJournalMode.c_str());
1681 :
1682 2 : CPL_IGNORE_RET_VAL(
1683 2 : sqlite3_exec(hDB, pszSQL, nullptr, nullptr, nullptr));
1684 : }
1685 :
1686 3789 : if (!bSecureDeleteFound)
1687 : {
1688 : // Turn on secure_delete by default (unless the user specifies a
1689 : // value of this pragma through OGR_SQLITE_PRAGMA)
1690 : // For example, Debian and Conda-Forge SQLite3 builds already turn on
1691 : // secure_delete.
1692 3788 : CPL_IGNORE_RET_VAL(sqlite3_exec(hDB, "PRAGMA secure_delete = 1",
1693 : nullptr, nullptr, nullptr));
1694 : }
1695 :
1696 3789 : SetCacheSize();
1697 3789 : SetSynchronous();
1698 3789 : if (bLoadExtensions)
1699 2463 : LoadExtensions();
1700 :
1701 3789 : return true;
1702 : }
1703 :
1704 : /************************************************************************/
1705 : /* OpenOrCreateDB() */
1706 : /************************************************************************/
1707 :
1708 1329 : bool OGRSQLiteDataSource::OpenOrCreateDB(int flagsIn,
1709 : bool bRegisterOGR2SQLiteExtensions)
1710 : {
1711 : {
1712 : // Make sure that OGR2SQLITE_static_register() doesn't instantiate
1713 : // its default OGR2SQLITEModule. Let's do it ourselves just afterwards
1714 : //
1715 : CPLConfigOptionSetter oSetter("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO",
1716 1329 : false);
1717 1329 : if (!OGRSQLiteBaseDataSource::OpenOrCreateDB(
1718 : flagsIn, bRegisterOGR2SQLiteExtensions,
1719 : /*bLoadExtensions=*/false))
1720 : {
1721 3 : return false;
1722 : }
1723 : }
1724 2652 : if (bRegisterOGR2SQLiteExtensions &&
1725 : // Do not run OGR2SQLITE_Setup() if called from ogrsqlitexecute.sql
1726 : // that will do it with other datasets.
1727 1326 : CPLTestBool(CPLGetConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "YES")))
1728 : {
1729 : // Make sure this is done before registering our custom functions
1730 : // to allow overriding Spatialite.
1731 665 : InitSpatialite();
1732 :
1733 665 : m_poSQLiteModule = OGR2SQLITE_Setup(this, this);
1734 : }
1735 : // We need to do LoadExtensions() after OGR2SQLITE_Setup(), otherwise
1736 : // tests in ogr_virtualogr.py::test_ogr_sqlite_load_extensions_load_self()
1737 : // will crash when trying to load libgdal as an extension (which is an
1738 : // errour we catch, but only if OGR2SQLITEModule has been created by
1739 : // above OGR2SQLITE_Setup()
1740 1326 : LoadExtensions();
1741 :
1742 : const char *pszPreludeStatements =
1743 1326 : CSLFetchNameValue(papszOpenOptions, "PRELUDE_STATEMENTS");
1744 1326 : if (pszPreludeStatements)
1745 : {
1746 1 : if (SQLCommand(hDB, pszPreludeStatements) != OGRERR_NONE)
1747 0 : return false;
1748 : }
1749 :
1750 1326 : return true;
1751 : }
1752 :
1753 : /************************************************************************/
1754 : /* PostInitSpatialite() */
1755 : /************************************************************************/
1756 :
1757 1017 : void OGRSQLiteDataSource::PostInitSpatialite()
1758 : {
1759 : #ifdef HAVE_SPATIALITE
1760 : const char *pszSqlitePragma =
1761 1017 : CPLGetConfigOption("OGR_SQLITE_PRAGMA", nullptr);
1762 1017 : OGRErr eErr = OGRERR_NONE;
1763 0 : if ((!pszSqlitePragma || !strstr(pszSqlitePragma, "trusted_schema")) &&
1764 : // Older sqlite versions don't have this pragma
1765 2032 : SQLGetInteger(hDB, "PRAGMA trusted_schema", &eErr) == 0 &&
1766 1015 : eErr == OGRERR_NONE)
1767 : {
1768 : // Spatialite <= 5.1.0 doesn't declare its functions as SQLITE_INNOCUOUS
1769 2030 : if (IsSpatialiteLoaded() && SpatialiteRequiresTrustedSchemaOn() &&
1770 1015 : AreSpatialiteTriggersSafe())
1771 : {
1772 1015 : CPLDebug("SQLITE", "Setting PRAGMA trusted_schema = 1");
1773 1015 : SQLCommand(hDB, "PRAGMA trusted_schema = 1");
1774 : }
1775 : }
1776 : #endif
1777 1017 : }
1778 :
1779 : /************************************************************************/
1780 : /* SpatialiteRequiresTrustedSchemaOn() */
1781 : /************************************************************************/
1782 :
1783 1016 : bool OGRSQLiteBaseDataSource::SpatialiteRequiresTrustedSchemaOn()
1784 : {
1785 : #ifdef HAVE_SPATIALITE
1786 : // Spatialite <= 5.1.0 doesn't declare its functions as SQLITE_INNOCUOUS
1787 1016 : if (GetSpatialiteVersionNumber() <= MakeSpatialiteVersionNumber(5, 1, 0))
1788 : {
1789 1016 : return true;
1790 : }
1791 : #endif
1792 0 : return false;
1793 : }
1794 :
1795 : /************************************************************************/
1796 : /* AreSpatialiteTriggersSafe() */
1797 : /************************************************************************/
1798 :
1799 1016 : bool OGRSQLiteBaseDataSource::AreSpatialiteTriggersSafe()
1800 : {
1801 : #ifdef HAVE_SPATIALITE
1802 : // Not totally sure about the minimum spatialite version, but 4.3a is fine
1803 1016 : return GetSpatialiteVersionNumber() >=
1804 2032 : MakeSpatialiteVersionNumber(4, 3, 0) &&
1805 2032 : SQLGetInteger(hDB, "SELECT CountUnsafeTriggers()", nullptr) == 0;
1806 : #else
1807 : return true;
1808 : #endif
1809 : }
1810 :
1811 : /************************************************************************/
1812 : /* GetInternalHandle() */
1813 : /************************************************************************/
1814 :
1815 : /* Used by MBTILES driver */
1816 61 : void *OGRSQLiteBaseDataSource::GetInternalHandle(const char *pszKey)
1817 : {
1818 61 : if (pszKey != nullptr && EQUAL(pszKey, "SQLITE_HANDLE"))
1819 61 : return hDB;
1820 0 : return nullptr;
1821 : }
1822 :
1823 : /************************************************************************/
1824 : /* Create() */
1825 : /************************************************************************/
1826 :
1827 367 : bool OGRSQLiteDataSource::Create(const char *pszNameIn,
1828 : CSLConstList papszOptions)
1829 : {
1830 734 : CPLString osCommand;
1831 :
1832 : const bool bUseTempFile =
1833 367 : CPLTestBool(CPLGetConfigOption(
1834 368 : "CPL_VSIL_USE_TEMP_FILE_FOR_RANDOM_WRITE", "NO")) &&
1835 1 : (VSIHasOptimizedReadMultiRange(pszNameIn) != FALSE ||
1836 1 : EQUAL(
1837 : CPLGetConfigOption("CPL_VSIL_USE_TEMP_FILE_FOR_RANDOM_WRITE", ""),
1838 367 : "FORCED"));
1839 :
1840 367 : if (bUseTempFile)
1841 : {
1842 1 : m_osFinalFilename = pszNameIn;
1843 1 : m_pszFilename = CPLStrdup(
1844 2 : CPLGenerateTempFilenameSafe(CPLGetFilename(pszNameIn)).c_str());
1845 1 : CPLDebug("SQLITE", "Creating temporary file %s", m_pszFilename);
1846 : }
1847 : else
1848 : {
1849 366 : m_pszFilename = CPLStrdup(pszNameIn);
1850 : }
1851 :
1852 : /* -------------------------------------------------------------------- */
1853 : /* Check that spatialite extensions are loaded if required to */
1854 : /* create a spatialite database */
1855 : /* -------------------------------------------------------------------- */
1856 367 : const bool bSpatialite = CPLFetchBool(papszOptions, "SPATIALITE", false);
1857 367 : const bool bMetadata = CPLFetchBool(papszOptions, "METADATA", true);
1858 :
1859 : if (bSpatialite)
1860 : {
1861 : #ifndef HAVE_SPATIALITE
1862 : CPLError(
1863 : CE_Failure, CPLE_NotSupported,
1864 : "OGR was built without libspatialite support\n"
1865 : "... sorry, creating/writing any SpatiaLite DB is unsupported");
1866 :
1867 : return false;
1868 : #endif
1869 : }
1870 :
1871 367 : m_bIsSpatiaLiteDB = bSpatialite;
1872 :
1873 : /* -------------------------------------------------------------------- */
1874 : /* Create the database file. */
1875 : /* -------------------------------------------------------------------- */
1876 367 : if (!OpenOrCreateDB(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, true))
1877 2 : return false;
1878 :
1879 : /* -------------------------------------------------------------------- */
1880 : /* Create the SpatiaLite metadata tables. */
1881 : /* -------------------------------------------------------------------- */
1882 365 : if (bSpatialite)
1883 : {
1884 52 : if (!InitSpatialite())
1885 : {
1886 0 : CPLError(CE_Failure, CPLE_NotSupported,
1887 : "Creating a Spatialite database, but Spatialite "
1888 : "extensions are not loaded.");
1889 0 : return false;
1890 : }
1891 :
1892 52 : PostInitSpatialite();
1893 :
1894 : #ifdef HAVE_RASTERLITE2
1895 : InitRasterLite2();
1896 : #endif
1897 :
1898 : /*
1899 : / SpatiaLite full support: calling InitSpatialMetadata()
1900 : /
1901 : / IMPORTANT NOTICE: on SpatiaLite any attempt aimed
1902 : / to directly CREATE "geometry_columns" and "spatial_ref_sys"
1903 : / [by-passing InitSpatialMetadata() as absolutely required]
1904 : / will severely [and irremediably] corrupt the DB !!!
1905 : */
1906 :
1907 52 : const char *pszVal = CSLFetchNameValue(papszOptions, "INIT_WITH_EPSG");
1908 52 : const int nSpatialiteVersionNumber = GetSpatialiteVersionNumber();
1909 53 : if (pszVal != nullptr && !CPLTestBool(pszVal) &&
1910 1 : nSpatialiteVersionNumber >= MakeSpatialiteVersionNumber(4, 0, 0))
1911 : {
1912 1 : if (nSpatialiteVersionNumber >=
1913 1 : MakeSpatialiteVersionNumber(4, 1, 0))
1914 1 : osCommand = "SELECT InitSpatialMetadata(1, 'NONE')";
1915 : else
1916 0 : osCommand = "SELECT InitSpatialMetadata('NONE')";
1917 : }
1918 : else
1919 : {
1920 : /* Since spatialite 4.1, InitSpatialMetadata() is no longer run */
1921 : /* into a transaction, which makes population of spatial_ref_sys */
1922 : /* from EPSG awfully slow. We have to use InitSpatialMetadata(1) */
1923 : /* to run within a transaction */
1924 51 : if (nSpatialiteVersionNumber >= 41)
1925 51 : osCommand = "SELECT InitSpatialMetadata(1)";
1926 : else
1927 0 : osCommand = "SELECT InitSpatialMetadata()";
1928 : }
1929 52 : if (SQLCommand(hDB, osCommand) != OGRERR_NONE)
1930 : {
1931 0 : return false;
1932 : }
1933 : }
1934 :
1935 : /* -------------------------------------------------------------------- */
1936 : /* Create the geometry_columns and spatial_ref_sys metadata tables. */
1937 : /* -------------------------------------------------------------------- */
1938 313 : else if (bMetadata)
1939 : {
1940 304 : if (SQLCommand(hDB, "CREATE TABLE geometry_columns ("
1941 : " f_table_name VARCHAR, "
1942 : " f_geometry_column VARCHAR, "
1943 : " geometry_type INTEGER, "
1944 : " coord_dimension INTEGER, "
1945 : " srid INTEGER,"
1946 : " geometry_format VARCHAR )"
1947 : ";"
1948 : "CREATE TABLE spatial_ref_sys ("
1949 : " srid INTEGER UNIQUE,"
1950 : " auth_name TEXT,"
1951 : " auth_srid TEXT,"
1952 304 : " srtext TEXT)") != OGRERR_NONE)
1953 : {
1954 0 : return false;
1955 : }
1956 : }
1957 :
1958 : /* -------------------------------------------------------------------- */
1959 : /* Optionally initialize the content of the spatial_ref_sys table */
1960 : /* with the EPSG database */
1961 : /* -------------------------------------------------------------------- */
1962 721 : if ((bSpatialite || bMetadata) &&
1963 356 : CPLFetchBool(papszOptions, "INIT_WITH_EPSG", false))
1964 : {
1965 2 : if (!InitWithEPSG())
1966 0 : return false;
1967 : }
1968 :
1969 730 : GDALOpenInfo oOpenInfo(m_pszFilename, GDAL_OF_VECTOR | GDAL_OF_UPDATE);
1970 365 : return Open(&oOpenInfo);
1971 : }
1972 :
1973 : /************************************************************************/
1974 : /* InitWithEPSG() */
1975 : /************************************************************************/
1976 :
1977 2 : bool OGRSQLiteDataSource::InitWithEPSG()
1978 : {
1979 4 : CPLString osCommand;
1980 :
1981 2 : if (m_bIsSpatiaLiteDB)
1982 : {
1983 : /*
1984 : / if v.2.4.0 (or any subsequent) InitWithEPSG make no sense at all
1985 : / because the EPSG dataset is already self-initialized at DB creation
1986 : */
1987 1 : int iSpatialiteVersion = GetSpatialiteVersionNumber();
1988 1 : if (iSpatialiteVersion >= MakeSpatialiteVersionNumber(2, 4, 0))
1989 1 : return true;
1990 : }
1991 :
1992 1 : if (SoftStartTransaction() != OGRERR_NONE)
1993 0 : return false;
1994 :
1995 2 : OGRSpatialReference oSRS;
1996 1 : int rc = SQLITE_OK;
1997 3 : for (int i = 0; i < 2 && rc == SQLITE_OK; i++)
1998 : {
1999 2 : PROJ_STRING_LIST crsCodeList = proj_get_codes_from_database(
2000 : OSRGetProjTLSContext(), "EPSG",
2001 : i == 0 ? PJ_TYPE_GEOGRAPHIC_2D_CRS : PJ_TYPE_PROJECTED_CRS, true);
2002 5670 : for (auto iterCode = crsCodeList; iterCode && *iterCode; ++iterCode)
2003 : {
2004 5668 : int nSRSId = atoi(*iterCode);
2005 :
2006 5668 : CPLPushErrorHandler(CPLQuietErrorHandler);
2007 5668 : oSRS.importFromEPSG(nSRSId);
2008 5668 : CPLPopErrorHandler();
2009 :
2010 5668 : if (m_bIsSpatiaLiteDB)
2011 : {
2012 0 : char *pszProj4 = nullptr;
2013 :
2014 0 : CPLPushErrorHandler(CPLQuietErrorHandler);
2015 0 : OGRErr eErr = oSRS.exportToProj4(&pszProj4);
2016 :
2017 0 : char *pszWKT = nullptr;
2018 0 : if (eErr == OGRERR_NONE &&
2019 0 : oSRS.exportToWkt(&pszWKT) != OGRERR_NONE)
2020 : {
2021 0 : CPLFree(pszWKT);
2022 0 : pszWKT = nullptr;
2023 0 : eErr = OGRERR_FAILURE;
2024 : }
2025 0 : CPLPopErrorHandler();
2026 :
2027 0 : if (eErr == OGRERR_NONE)
2028 : {
2029 0 : const char *pszProjCS = oSRS.GetAttrValue("PROJCS");
2030 0 : if (pszProjCS == nullptr)
2031 0 : pszProjCS = oSRS.GetAttrValue("GEOGCS");
2032 :
2033 0 : const char *pszSRTEXTColName = GetSRTEXTColName();
2034 0 : if (pszSRTEXTColName != nullptr)
2035 : {
2036 : /* the SPATIAL_REF_SYS table supports a SRS_WKT column
2037 : */
2038 0 : if (pszProjCS)
2039 : osCommand.Printf(
2040 : "INSERT INTO spatial_ref_sys "
2041 : "(srid, auth_name, auth_srid, ref_sys_name, "
2042 : "proj4text, %s) "
2043 : "VALUES (%d, 'EPSG', '%d', ?, ?, ?)",
2044 0 : pszSRTEXTColName, nSRSId, nSRSId);
2045 : else
2046 : osCommand.Printf(
2047 : "INSERT INTO spatial_ref_sys "
2048 : "(srid, auth_name, auth_srid, proj4text, %s) "
2049 : "VALUES (%d, 'EPSG', '%d', ?, ?)",
2050 0 : pszSRTEXTColName, nSRSId, nSRSId);
2051 : }
2052 : else
2053 : {
2054 : /* the SPATIAL_REF_SYS table does not support a SRS_WKT
2055 : * column */
2056 0 : if (pszProjCS)
2057 : osCommand.Printf("INSERT INTO spatial_ref_sys "
2058 : "(srid, auth_name, auth_srid, "
2059 : "ref_sys_name, proj4text) "
2060 : "VALUES (%d, 'EPSG', '%d', ?, ?)",
2061 0 : nSRSId, nSRSId);
2062 : else
2063 : osCommand.Printf(
2064 : "INSERT INTO spatial_ref_sys "
2065 : "(srid, auth_name, auth_srid, proj4text) "
2066 : "VALUES (%d, 'EPSG', '%d', ?)",
2067 0 : nSRSId, nSRSId);
2068 : }
2069 :
2070 0 : sqlite3_stmt *hInsertStmt = prepareSql(hDB, osCommand, -1);
2071 :
2072 0 : if (pszProjCS)
2073 : {
2074 0 : if (rc == SQLITE_OK)
2075 0 : rc = sqlite3_bind_text(hInsertStmt, 1, pszProjCS,
2076 : -1, SQLITE_STATIC);
2077 0 : if (rc == SQLITE_OK)
2078 0 : rc = sqlite3_bind_text(hInsertStmt, 2, pszProj4, -1,
2079 : SQLITE_STATIC);
2080 0 : if (pszSRTEXTColName != nullptr)
2081 : {
2082 : /* the SPATIAL_REF_SYS table supports a SRS_WKT
2083 : * column */
2084 0 : if (rc == SQLITE_OK && pszWKT != nullptr)
2085 0 : rc = sqlite3_bind_text(hInsertStmt, 3, pszWKT,
2086 : -1, SQLITE_STATIC);
2087 : }
2088 : }
2089 : else
2090 : {
2091 0 : if (rc == SQLITE_OK)
2092 0 : rc = sqlite3_bind_text(hInsertStmt, 1, pszProj4, -1,
2093 : SQLITE_STATIC);
2094 0 : if (pszSRTEXTColName != nullptr)
2095 : {
2096 : /* the SPATIAL_REF_SYS table supports a SRS_WKT
2097 : * column */
2098 0 : if (rc == SQLITE_OK && pszWKT != nullptr)
2099 0 : rc = sqlite3_bind_text(hInsertStmt, 2, pszWKT,
2100 : -1, SQLITE_STATIC);
2101 : }
2102 : }
2103 :
2104 0 : if (rc == SQLITE_OK)
2105 0 : rc = sqlite3_step(hInsertStmt);
2106 :
2107 0 : if (rc != SQLITE_OK && rc != SQLITE_DONE)
2108 : {
2109 0 : CPLError(CE_Failure, CPLE_AppDefined,
2110 : "Cannot insert %s into spatial_ref_sys : %s",
2111 : pszProj4, sqlite3_errmsg(hDB));
2112 :
2113 0 : sqlite3_finalize(hInsertStmt);
2114 0 : CPLFree(pszProj4);
2115 0 : CPLFree(pszWKT);
2116 0 : break;
2117 : }
2118 0 : rc = SQLITE_OK;
2119 :
2120 0 : sqlite3_finalize(hInsertStmt);
2121 : }
2122 :
2123 0 : CPLFree(pszProj4);
2124 0 : CPLFree(pszWKT);
2125 : }
2126 : else
2127 : {
2128 5668 : char *pszWKT = nullptr;
2129 5668 : CPLPushErrorHandler(CPLQuietErrorHandler);
2130 5668 : bool bSuccess = (oSRS.exportToWkt(&pszWKT) == OGRERR_NONE);
2131 5668 : CPLPopErrorHandler();
2132 5668 : if (bSuccess)
2133 : {
2134 : osCommand.Printf("INSERT INTO spatial_ref_sys "
2135 : "(srid, auth_name, auth_srid, srtext) "
2136 : "VALUES (%d, 'EPSG', '%d', ?)",
2137 5668 : nSRSId, nSRSId);
2138 :
2139 : sqlite3_stmt *hInsertStmt =
2140 5668 : prepareSql(hDB, osCommand.c_str());
2141 :
2142 5668 : if (hInsertStmt)
2143 5668 : rc = sqlite3_bind_text(hInsertStmt, 1, pszWKT, -1,
2144 : SQLITE_STATIC);
2145 : else
2146 0 : rc = SQLITE_ERROR;
2147 :
2148 5668 : if (rc == SQLITE_OK)
2149 5668 : rc = sqlite3_step(hInsertStmt);
2150 :
2151 5668 : if (rc != SQLITE_OK && rc != SQLITE_DONE)
2152 : {
2153 0 : CPLError(CE_Failure, CPLE_AppDefined,
2154 : "Cannot insert %s into spatial_ref_sys : %s",
2155 : pszWKT, sqlite3_errmsg(hDB));
2156 :
2157 0 : sqlite3_finalize(hInsertStmt);
2158 0 : CPLFree(pszWKT);
2159 0 : break;
2160 : }
2161 5668 : rc = SQLITE_OK;
2162 :
2163 5668 : sqlite3_finalize(hInsertStmt);
2164 : }
2165 :
2166 5668 : CPLFree(pszWKT);
2167 : }
2168 : }
2169 :
2170 2 : proj_string_list_destroy(crsCodeList);
2171 : }
2172 :
2173 1 : if (rc == SQLITE_OK)
2174 : {
2175 1 : if (SoftCommitTransaction() != OGRERR_NONE)
2176 0 : return false;
2177 1 : return true;
2178 : }
2179 : else
2180 : {
2181 0 : SoftRollbackTransaction();
2182 0 : return false;
2183 : }
2184 : }
2185 :
2186 : /************************************************************************/
2187 : /* ReloadLayers() */
2188 : /************************************************************************/
2189 :
2190 659 : void OGRSQLiteDataSource::ReloadLayers()
2191 : {
2192 659 : m_apoLayers.clear();
2193 :
2194 659 : GDALOpenInfo oOpenInfo(m_pszFilename,
2195 1318 : GDAL_OF_VECTOR | (GetUpdate() ? GDAL_OF_UPDATE : 0));
2196 659 : Open(&oOpenInfo);
2197 659 : }
2198 :
2199 : /************************************************************************/
2200 : /* Open() */
2201 : /************************************************************************/
2202 :
2203 1988 : bool OGRSQLiteDataSource::Open(GDALOpenInfo *poOpenInfo)
2204 :
2205 : {
2206 1988 : const char *pszNewName = poOpenInfo->pszFilename;
2207 1988 : CPLAssert(m_apoLayers.empty());
2208 1988 : eAccess = poOpenInfo->eAccess;
2209 1988 : nOpenFlags = poOpenInfo->nOpenFlags & ~GDAL_OF_THREAD_SAFE;
2210 1988 : SetDescription(pszNewName);
2211 :
2212 1988 : if (m_pszFilename == nullptr)
2213 : {
2214 : #ifdef HAVE_RASTERLITE2
2215 : if (STARTS_WITH_CI(pszNewName, "RASTERLITE2:") &&
2216 : (nOpenFlags & GDAL_OF_RASTER) != 0)
2217 : {
2218 : char **papszTokens =
2219 : CSLTokenizeString2(pszNewName, ":", CSLT_HONOURSTRINGS);
2220 : if (CSLCount(papszTokens) < 2)
2221 : {
2222 : CSLDestroy(papszTokens);
2223 : return false;
2224 : }
2225 : m_pszFilename = CPLStrdup(SQLUnescape(papszTokens[1]));
2226 : CSLDestroy(papszTokens);
2227 : }
2228 : else
2229 : #endif
2230 964 : if (STARTS_WITH_CI(pszNewName, "SQLITE:"))
2231 : {
2232 79 : m_pszFilename = CPLStrdup(pszNewName + strlen("SQLITE:"));
2233 : }
2234 : else
2235 : {
2236 885 : m_pszFilename = CPLStrdup(pszNewName);
2237 885 : if (poOpenInfo->pabyHeader &&
2238 835 : STARTS_WITH(
2239 : reinterpret_cast<const char *>(poOpenInfo->pabyHeader),
2240 : "SQLite format 3"))
2241 : {
2242 834 : m_bCallUndeclareFileNotToOpen = true;
2243 834 : GDALOpenInfoDeclareFileNotToOpen(m_pszFilename,
2244 834 : poOpenInfo->pabyHeader,
2245 : poOpenInfo->nHeaderBytes);
2246 : }
2247 : }
2248 : }
2249 1988 : SetPhysicalFilename(m_pszFilename);
2250 :
2251 : VSIStatBufL sStat;
2252 1988 : if (VSIStatL(m_pszFilename, &sStat) == 0)
2253 : {
2254 1919 : m_nFileTimestamp = sStat.st_mtime;
2255 : }
2256 :
2257 1988 : if (poOpenInfo->papszOpenOptions)
2258 : {
2259 11 : CSLDestroy(papszOpenOptions);
2260 11 : papszOpenOptions = CSLDuplicate(poOpenInfo->papszOpenOptions);
2261 : }
2262 :
2263 1988 : const bool bListVectorLayers = (nOpenFlags & GDAL_OF_VECTOR) != 0;
2264 :
2265 : const bool bListAllTables =
2266 3976 : bListVectorLayers &&
2267 3976 : CPLTestBool(CSLFetchNameValueDef(
2268 1988 : papszOpenOptions, "LIST_ALL_TABLES",
2269 1988 : CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "NO")));
2270 :
2271 : // Don't list by default: there might be some security implications
2272 : // if a user is provided with a file and doesn't know that there are
2273 : // virtual OGR tables in it.
2274 : const bool bListVirtualOGRLayers =
2275 3976 : bListVectorLayers &&
2276 3976 : CPLTestBool(CSLFetchNameValueDef(
2277 1988 : papszOpenOptions, "LIST_VIRTUAL_OGR",
2278 1988 : CPLGetConfigOption("OGR_SQLITE_LIST_VIRTUAL_OGR", "NO")));
2279 :
2280 : /* -------------------------------------------------------------------- */
2281 : /* Try to open the sqlite database properly now. */
2282 : /* -------------------------------------------------------------------- */
2283 1988 : if (hDB == nullptr)
2284 : {
2285 : #ifdef ENABLE_SQL_SQLITE_FORMAT
2286 : // SQLite -wal locking appears to be extremely fragile. In particular
2287 : // if we have a file descriptor opened on the file while sqlite3_open
2288 : // is called, then it will mis-behave (a process opening in update mode
2289 : // the file and closing it will remove the -wal file !)
2290 : // So make sure that the GDALOpenInfo object goes out of scope before
2291 : // going on.
2292 : {
2293 964 : GDALOpenInfo oOpenInfo(m_pszFilename, GA_ReadOnly);
2294 964 : if (oOpenInfo.pabyHeader &&
2295 914 : (STARTS_WITH(
2296 : reinterpret_cast<const char *>(oOpenInfo.pabyHeader),
2297 913 : "-- SQL SQLITE") ||
2298 913 : STARTS_WITH(
2299 : reinterpret_cast<const char *>(oOpenInfo.pabyHeader),
2300 913 : "-- SQL RASTERLITE") ||
2301 913 : STARTS_WITH(
2302 : reinterpret_cast<const char *>(oOpenInfo.pabyHeader),
2303 2 : "-- SQL MBTILES")) &&
2304 2 : oOpenInfo.fpL != nullptr)
2305 : {
2306 2 : if (sqlite3_open_v2(":memory:", &hDB, SQLITE_OPEN_READWRITE,
2307 2 : nullptr) != SQLITE_OK)
2308 : {
2309 0 : return false;
2310 : }
2311 :
2312 : // We need it here for ST_MinX() and the like
2313 2 : InitSpatialite();
2314 :
2315 2 : PostInitSpatialite();
2316 :
2317 : // Ingest the lines of the dump
2318 2 : VSIFSeekL(oOpenInfo.fpL, 0, SEEK_SET);
2319 : const char *pszLine;
2320 24 : while ((pszLine = CPLReadLineL(oOpenInfo.fpL)) != nullptr)
2321 : {
2322 22 : if (STARTS_WITH(pszLine, "--"))
2323 2 : continue;
2324 :
2325 20 : if (!SQLCheckLineIsSafe(pszLine))
2326 0 : return false;
2327 :
2328 20 : char *pszErrMsg = nullptr;
2329 20 : if (sqlite3_exec(hDB, pszLine, nullptr, nullptr,
2330 20 : &pszErrMsg) != SQLITE_OK)
2331 : {
2332 0 : if (pszErrMsg)
2333 : {
2334 0 : CPLDebug("SQLITE", "Error %s at line %s", pszErrMsg,
2335 : pszLine);
2336 : }
2337 : }
2338 20 : sqlite3_free(pszErrMsg);
2339 : }
2340 : }
2341 : }
2342 964 : if (hDB == nullptr)
2343 : #endif
2344 : {
2345 962 : if (poOpenInfo->fpL)
2346 : {
2347 : // See above comment about -wal locking for the importance of
2348 : // closing that file, prior to calling sqlite3_open()
2349 810 : VSIFCloseL(poOpenInfo->fpL);
2350 810 : poOpenInfo->fpL = nullptr;
2351 : }
2352 962 : if (!OpenOrCreateDB(GetUpdate() ? SQLITE_OPEN_READWRITE
2353 : : SQLITE_OPEN_READONLY,
2354 : true))
2355 : {
2356 1 : poOpenInfo->fpL =
2357 1 : VSIFOpenL(poOpenInfo->pszFilename,
2358 1 : poOpenInfo->eAccess == GA_Update ? "rb+" : "rb");
2359 1 : return false;
2360 : }
2361 : }
2362 :
2363 963 : InitSpatialite();
2364 :
2365 963 : PostInitSpatialite();
2366 :
2367 : #ifdef HAVE_RASTERLITE2
2368 : InitRasterLite2();
2369 : #endif
2370 : }
2371 :
2372 : #ifdef HAVE_RASTERLITE2
2373 : if (STARTS_WITH_CI(pszNewName, "RASTERLITE2:") &&
2374 : (nOpenFlags & GDAL_OF_RASTER) != 0)
2375 : {
2376 : return OpenRasterSubDataset(pszNewName);
2377 : }
2378 : #endif
2379 :
2380 : /* -------------------------------------------------------------------- */
2381 : /* If we have a GEOMETRY_COLUMNS tables, initialize on the basis */
2382 : /* of that. */
2383 : /* -------------------------------------------------------------------- */
2384 : CPLHashSet *hSet =
2385 1987 : CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
2386 :
2387 1987 : char **papszResult = nullptr;
2388 1987 : char *pszErrMsg = nullptr;
2389 1987 : int nRowCount = 0;
2390 1987 : int nColCount = 0;
2391 1987 : int rc = sqlite3_get_table(
2392 : hDB,
2393 : "SELECT f_table_name, f_geometry_column, geometry_type, "
2394 : "coord_dimension, geometry_format, srid"
2395 : " FROM geometry_columns "
2396 : "LIMIT 10000",
2397 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
2398 :
2399 1987 : if (rc == SQLITE_OK)
2400 : {
2401 550 : CPLDebug("SQLITE", "OGR style SQLite DB found !");
2402 :
2403 550 : m_bHaveGeometryColumns = true;
2404 :
2405 798 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2406 : {
2407 248 : char **papszRow = papszResult + iRow * 6 + 6;
2408 248 : const char *pszTableName = papszRow[0];
2409 248 : const char *pszGeomCol = papszRow[1];
2410 :
2411 248 : if (pszTableName == nullptr || pszGeomCol == nullptr)
2412 0 : continue;
2413 :
2414 496 : m_aoMapTableToSetOfGeomCols[pszTableName].insert(
2415 248 : CPLString(pszGeomCol).tolower());
2416 : }
2417 :
2418 795 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2419 : {
2420 248 : char **papszRow = papszResult + iRow * 6 + 6;
2421 248 : const char *pszTableName = papszRow[0];
2422 :
2423 248 : if (pszTableName == nullptr)
2424 0 : continue;
2425 :
2426 248 : if (GDALDataset::GetLayerByName(pszTableName) == nullptr)
2427 : {
2428 237 : const bool bRet = OpenTable(pszTableName, true, false,
2429 : /* bMayEmitError = */ true);
2430 237 : if (!bRet)
2431 : {
2432 3 : CPLDebug("SQLITE", "Failed to open layer %s", pszTableName);
2433 3 : sqlite3_free_table(papszResult);
2434 3 : CPLHashSetDestroy(hSet);
2435 3 : return false;
2436 : }
2437 : }
2438 :
2439 245 : if (bListAllTables)
2440 2 : CPLHashSetInsert(hSet, CPLStrdup(pszTableName));
2441 : }
2442 :
2443 547 : sqlite3_free_table(papszResult);
2444 :
2445 : /* --------------------------------------------------------------------
2446 : */
2447 : /* Detect VirtualOGR layers */
2448 : /* --------------------------------------------------------------------
2449 : */
2450 547 : if (bListVirtualOGRLayers)
2451 : {
2452 2 : rc = sqlite3_get_table(hDB,
2453 : "SELECT name, sql FROM sqlite_master "
2454 : "WHERE sql LIKE 'CREATE VIRTUAL TABLE %' "
2455 : "LIMIT 10000",
2456 : &papszResult, &nRowCount, &nColCount,
2457 : &pszErrMsg);
2458 :
2459 2 : if (rc == SQLITE_OK)
2460 : {
2461 4 : for (int iRow = 0; iRow < nRowCount; iRow++)
2462 : {
2463 2 : char **papszRow = papszResult + iRow * 2 + 2;
2464 2 : const char *pszName = papszRow[0];
2465 2 : const char *pszSQL = papszRow[1];
2466 2 : if (pszName == nullptr || pszSQL == nullptr)
2467 0 : continue;
2468 :
2469 2 : if (strstr(pszSQL, "VirtualOGR"))
2470 : {
2471 2 : OpenVirtualTable(pszName, pszSQL);
2472 :
2473 2 : if (bListAllTables)
2474 0 : CPLHashSetInsert(hSet, CPLStrdup(pszName));
2475 : }
2476 : }
2477 : }
2478 : else
2479 : {
2480 0 : CPLError(CE_Failure, CPLE_AppDefined,
2481 : "Unable to fetch list of tables: %s", pszErrMsg);
2482 0 : sqlite3_free(pszErrMsg);
2483 : }
2484 :
2485 2 : sqlite3_free_table(papszResult);
2486 : }
2487 :
2488 547 : if (bListAllTables)
2489 1 : goto all_tables;
2490 :
2491 546 : CPLHashSetDestroy(hSet);
2492 :
2493 546 : if (nOpenFlags & GDAL_OF_RASTER)
2494 : {
2495 0 : bool bRet = OpenRaster();
2496 0 : if (!bRet && !(nOpenFlags & GDAL_OF_VECTOR))
2497 0 : return false;
2498 : }
2499 :
2500 546 : return true;
2501 : }
2502 :
2503 : /* -------------------------------------------------------------------- */
2504 : /* Otherwise we can deal with SpatiaLite database. */
2505 : /* -------------------------------------------------------------------- */
2506 1437 : sqlite3_free(pszErrMsg);
2507 1437 : rc = sqlite3_get_table(hDB,
2508 : "SELECT sm.name, gc.f_geometry_column, "
2509 : "gc.type, gc.coord_dimension, gc.srid, "
2510 : "gc.spatial_index_enabled FROM geometry_columns gc "
2511 : "JOIN sqlite_master sm ON "
2512 : "LOWER(gc.f_table_name)=LOWER(sm.name) "
2513 : "LIMIT 10000",
2514 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
2515 1437 : if (rc != SQLITE_OK)
2516 : {
2517 : /* Test with SpatiaLite 4.0 schema */
2518 1431 : sqlite3_free(pszErrMsg);
2519 1431 : rc = sqlite3_get_table(
2520 : hDB,
2521 : "SELECT sm.name, gc.f_geometry_column, "
2522 : "gc.geometry_type, gc.coord_dimension, gc.srid, "
2523 : "gc.spatial_index_enabled FROM geometry_columns gc "
2524 : "JOIN sqlite_master sm ON "
2525 : "LOWER(gc.f_table_name)=LOWER(sm.name) "
2526 : "LIMIT 10000",
2527 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
2528 1431 : if (rc == SQLITE_OK)
2529 : {
2530 1196 : m_bSpatialite4Layout = true;
2531 1196 : m_nUndefinedSRID = 0;
2532 : }
2533 : }
2534 :
2535 1437 : if (rc == SQLITE_OK)
2536 : {
2537 1202 : m_bIsSpatiaLiteDB = true;
2538 1202 : m_bHaveGeometryColumns = true;
2539 :
2540 1202 : int iSpatialiteVersion = -1;
2541 :
2542 : /* Only enables write-mode if linked against SpatiaLite */
2543 1202 : if (IsSpatialiteLoaded())
2544 : {
2545 1202 : iSpatialiteVersion = GetSpatialiteVersionNumber();
2546 : }
2547 0 : else if (GetUpdate())
2548 : {
2549 0 : CPLError(CE_Failure, CPLE_AppDefined,
2550 : "SpatiaLite%s DB found, "
2551 : "but updating tables disabled because no linking against "
2552 : "spatialite library !",
2553 0 : (m_bSpatialite4Layout) ? " v4" : "");
2554 0 : sqlite3_free_table(papszResult);
2555 0 : CPLHashSetDestroy(hSet);
2556 1202 : return false;
2557 : }
2558 :
2559 2361 : if (m_bSpatialite4Layout && GetUpdate() && iSpatialiteVersion > 0 &&
2560 1159 : iSpatialiteVersion < MakeSpatialiteVersionNumber(4, 0, 0))
2561 : {
2562 0 : CPLError(CE_Failure, CPLE_AppDefined,
2563 : "SpatiaLite v4 DB found, "
2564 : "but updating tables disabled because runtime spatialite "
2565 : "library is v%d.%d.%d !",
2566 : iSpatialiteVersion / 10000,
2567 0 : (iSpatialiteVersion % 10000) / 100,
2568 : (iSpatialiteVersion % 100));
2569 0 : sqlite3_free_table(papszResult);
2570 0 : CPLHashSetDestroy(hSet);
2571 0 : return false;
2572 : }
2573 : else
2574 : {
2575 1202 : CPLDebug("SQLITE", "SpatiaLite%s DB found !",
2576 1202 : (m_bSpatialite4Layout) ? " v4" : "");
2577 : }
2578 :
2579 : // List RasterLite2 coverages, so as to avoid listing corresponding
2580 : // technical tables
2581 1202 : std::set<CPLString> aoSetTablesToIgnore;
2582 1202 : if (m_bSpatialite4Layout)
2583 : {
2584 1196 : char **papszResults2 = nullptr;
2585 1196 : int nRowCount2 = 0, nColCount2 = 0;
2586 1196 : rc = sqlite3_get_table(
2587 : hDB,
2588 : "SELECT name FROM sqlite_master WHERE "
2589 : "type = 'table' AND name = 'raster_coverages'",
2590 : &papszResults2, &nRowCount2, &nColCount2, nullptr);
2591 1196 : sqlite3_free_table(papszResults2);
2592 1196 : if (rc == SQLITE_OK && nRowCount2 == 1)
2593 : {
2594 0 : papszResults2 = nullptr;
2595 0 : nRowCount2 = 0;
2596 0 : nColCount2 = 0;
2597 0 : rc = sqlite3_get_table(
2598 : hDB,
2599 : "SELECT coverage_name FROM raster_coverages "
2600 : "LIMIT 10000",
2601 : &papszResults2, &nRowCount2, &nColCount2, nullptr);
2602 0 : if (rc == SQLITE_OK)
2603 : {
2604 0 : for (int i = 0; i < nRowCount2; ++i)
2605 : {
2606 0 : const char *const *papszRow = papszResults2 + i * 1 + 1;
2607 0 : if (papszRow[0] != nullptr)
2608 : {
2609 0 : aoSetTablesToIgnore.insert(CPLString(papszRow[0]) +
2610 0 : "_sections");
2611 0 : aoSetTablesToIgnore.insert(CPLString(papszRow[0]) +
2612 0 : "_tiles");
2613 : }
2614 : }
2615 : }
2616 0 : sqlite3_free_table(papszResults2);
2617 : }
2618 : }
2619 :
2620 1546 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2621 : {
2622 344 : char **papszRow = papszResult + iRow * 6 + 6;
2623 344 : const char *pszTableName = papszRow[0];
2624 344 : const char *pszGeomCol = papszRow[1];
2625 :
2626 344 : if (pszTableName == nullptr || pszGeomCol == nullptr)
2627 0 : continue;
2628 688 : if (!bListAllTables &&
2629 344 : cpl::contains(aoSetTablesToIgnore, pszTableName))
2630 : {
2631 0 : continue;
2632 : }
2633 :
2634 688 : m_aoMapTableToSetOfGeomCols[pszTableName].insert(
2635 344 : CPLString(pszGeomCol).tolower());
2636 : }
2637 :
2638 1546 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2639 : {
2640 344 : char **papszRow = papszResult + iRow * 6 + 6;
2641 344 : const char *pszTableName = papszRow[0];
2642 :
2643 344 : if (pszTableName == nullptr)
2644 0 : continue;
2645 688 : if (!bListAllTables &&
2646 344 : cpl::contains(aoSetTablesToIgnore, pszTableName))
2647 : {
2648 0 : continue;
2649 : }
2650 :
2651 344 : if (GDALDataset::GetLayerByName(pszTableName) == nullptr)
2652 337 : OpenTable(pszTableName, true, false,
2653 : /* bMayEmitError = */ true);
2654 344 : if (bListAllTables)
2655 0 : CPLHashSetInsert(hSet, CPLStrdup(pszTableName));
2656 : }
2657 :
2658 1202 : sqlite3_free_table(papszResult);
2659 1202 : papszResult = nullptr;
2660 :
2661 : /* --------------------------------------------------------------------
2662 : */
2663 : /* Detect VirtualShape, VirtualXL and VirtualOGR layers */
2664 : /* --------------------------------------------------------------------
2665 : */
2666 : rc =
2667 1202 : sqlite3_get_table(hDB,
2668 : "SELECT name, sql FROM sqlite_master "
2669 : "WHERE sql LIKE 'CREATE VIRTUAL TABLE %' "
2670 : "LIMIT 10000",
2671 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
2672 :
2673 1202 : if (rc == SQLITE_OK)
2674 : {
2675 4000 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2676 : {
2677 2798 : char **papszRow = papszResult + iRow * 2 + 2;
2678 2798 : const char *pszName = papszRow[0];
2679 2798 : const char *pszSQL = papszRow[1];
2680 2798 : if (pszName == nullptr || pszSQL == nullptr)
2681 0 : continue;
2682 :
2683 5596 : if ((IsSpatialiteLoaded() && (strstr(pszSQL, "VirtualShape") ||
2684 5596 : strstr(pszSQL, "VirtualXL"))) ||
2685 0 : (bListVirtualOGRLayers && strstr(pszSQL, "VirtualOGR")))
2686 : {
2687 1 : OpenVirtualTable(pszName, pszSQL);
2688 :
2689 1 : if (bListAllTables)
2690 0 : CPLHashSetInsert(hSet, CPLStrdup(pszName));
2691 : }
2692 : }
2693 : }
2694 : else
2695 : {
2696 0 : CPLError(CE_Failure, CPLE_AppDefined,
2697 : "Unable to fetch list of tables: %s", pszErrMsg);
2698 0 : sqlite3_free(pszErrMsg);
2699 : }
2700 :
2701 1202 : sqlite3_free_table(papszResult);
2702 1202 : papszResult = nullptr;
2703 :
2704 : /* --------------------------------------------------------------------
2705 : */
2706 : /* Detect spatial views */
2707 : /* --------------------------------------------------------------------
2708 : */
2709 :
2710 1202 : rc = sqlite3_get_table(hDB,
2711 : "SELECT view_name, view_geometry, view_rowid, "
2712 : "f_table_name, f_geometry_column "
2713 : "FROM views_geometry_columns "
2714 : "LIMIT 10000",
2715 : &papszResult, &nRowCount, &nColCount, nullptr);
2716 1202 : if (rc == SQLITE_OK)
2717 : {
2718 1205 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2719 : {
2720 5 : char **papszRow = papszResult + iRow * 5 + 5;
2721 5 : const char *pszViewName = papszRow[0];
2722 5 : const char *pszViewGeometry = papszRow[1];
2723 5 : const char *pszViewRowid = papszRow[2];
2724 5 : const char *pszTableName = papszRow[3];
2725 5 : const char *pszGeometryColumn = papszRow[4];
2726 :
2727 5 : if (pszViewName == nullptr || pszViewGeometry == nullptr ||
2728 5 : pszViewRowid == nullptr || pszTableName == nullptr ||
2729 : pszGeometryColumn == nullptr)
2730 0 : continue;
2731 :
2732 5 : OpenView(pszViewName, pszViewGeometry, pszViewRowid,
2733 : pszTableName, pszGeometryColumn);
2734 :
2735 5 : if (bListAllTables)
2736 0 : CPLHashSetInsert(hSet, CPLStrdup(pszViewName));
2737 : }
2738 1200 : sqlite3_free_table(papszResult);
2739 : }
2740 :
2741 1202 : if (bListAllTables)
2742 0 : goto all_tables;
2743 :
2744 1202 : CPLHashSetDestroy(hSet);
2745 :
2746 1202 : if (nOpenFlags & GDAL_OF_RASTER)
2747 : {
2748 1 : bool bRet = OpenRaster();
2749 1 : if (!bRet && !(nOpenFlags & GDAL_OF_VECTOR))
2750 0 : return false;
2751 : }
2752 :
2753 1202 : return true;
2754 : }
2755 :
2756 : /* -------------------------------------------------------------------- */
2757 : /* Otherwise our final resort is to return all tables and views */
2758 : /* as non-spatial tables. */
2759 : /* -------------------------------------------------------------------- */
2760 235 : sqlite3_free(pszErrMsg);
2761 :
2762 236 : all_tables:
2763 236 : rc = sqlite3_get_table(hDB,
2764 : "SELECT name, type FROM sqlite_master "
2765 : "WHERE type IN ('table','view') "
2766 : "UNION ALL "
2767 : "SELECT name, type FROM sqlite_temp_master "
2768 : "WHERE type IN ('table','view') "
2769 : "ORDER BY 1 "
2770 : "LIMIT 10000",
2771 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
2772 :
2773 236 : if (rc != SQLITE_OK)
2774 : {
2775 0 : CPLError(CE_Failure, CPLE_AppDefined,
2776 : "Unable to fetch list of tables: %s", pszErrMsg);
2777 0 : sqlite3_free(pszErrMsg);
2778 0 : CPLHashSetDestroy(hSet);
2779 0 : return false;
2780 : }
2781 :
2782 600 : for (int iRow = 0; iRow < nRowCount; iRow++)
2783 : {
2784 364 : const char *pszTableName = papszResult[2 * (iRow + 1) + 0];
2785 364 : const char *pszType = papszResult[2 * (iRow + 1) + 1];
2786 728 : if (pszTableName != nullptr &&
2787 364 : CPLHashSetLookup(hSet, pszTableName) == nullptr)
2788 : {
2789 362 : const bool bIsTable =
2790 362 : pszType != nullptr && strcmp(pszType, "table") == 0;
2791 362 : OpenTable(pszTableName, bIsTable, false,
2792 : /* bMayEmitError = */ true);
2793 : }
2794 : }
2795 :
2796 236 : sqlite3_free_table(papszResult);
2797 236 : CPLHashSetDestroy(hSet);
2798 :
2799 236 : if (nOpenFlags & GDAL_OF_RASTER)
2800 : {
2801 2 : bool bRet = OpenRaster();
2802 2 : if (!bRet && !(nOpenFlags & GDAL_OF_VECTOR))
2803 0 : return false;
2804 : }
2805 :
2806 236 : return true;
2807 : }
2808 :
2809 : /************************************************************************/
2810 : /* OpenVirtualTable() */
2811 : /************************************************************************/
2812 :
2813 13 : bool OGRSQLiteDataSource::OpenVirtualTable(const char *pszName,
2814 : const char *pszSQL)
2815 : {
2816 13 : int nSRID = m_nUndefinedSRID;
2817 13 : const char *pszVirtualShape = strstr(pszSQL, "VirtualShape");
2818 13 : if (pszVirtualShape != nullptr)
2819 : {
2820 3 : const char *pszParenthesis = strchr(pszVirtualShape, '(');
2821 3 : if (pszParenthesis)
2822 : {
2823 : /* CREATE VIRTUAL TABLE table_name VirtualShape(shapename, codepage,
2824 : * srid) */
2825 : /* Extract 3rd parameter */
2826 : char **papszTokens =
2827 3 : CSLTokenizeString2(pszParenthesis + 1, ",", CSLT_HONOURSTRINGS);
2828 3 : if (CSLCount(papszTokens) == 3)
2829 : {
2830 3 : nSRID = atoi(papszTokens[2]);
2831 : }
2832 3 : CSLDestroy(papszTokens);
2833 : }
2834 : }
2835 :
2836 13 : if (OpenTable(pszName, true, pszVirtualShape != nullptr,
2837 : /* bMayEmitError = */ true))
2838 : {
2839 13 : OGRSQLiteLayer *poLayer = m_apoLayers.back().get();
2840 13 : if (poLayer->GetLayerDefn()->GetGeomFieldCount() == 1)
2841 : {
2842 : OGRSQLiteGeomFieldDefn *poGeomFieldDefn =
2843 3 : poLayer->myGetLayerDefn()->myGetGeomFieldDefn(0);
2844 3 : poGeomFieldDefn->m_eGeomFormat = OSGF_SpatiaLite;
2845 3 : if (nSRID > 0)
2846 : {
2847 0 : poGeomFieldDefn->m_nSRSId = nSRID;
2848 0 : poGeomFieldDefn->SetSpatialRef(FetchSRS(nSRID));
2849 : }
2850 : }
2851 :
2852 13 : OGRFeature *poFeature = poLayer->GetNextFeature();
2853 13 : if (poFeature)
2854 : {
2855 12 : OGRGeometry *poGeom = poFeature->GetGeometryRef();
2856 12 : if (poGeom)
2857 : {
2858 6 : whileUnsealing(poLayer->GetLayerDefn())
2859 3 : ->SetGeomType(poGeom->getGeometryType());
2860 : }
2861 12 : delete poFeature;
2862 : }
2863 13 : poLayer->ResetReading();
2864 13 : return true;
2865 : }
2866 :
2867 0 : return false;
2868 : }
2869 :
2870 : /************************************************************************/
2871 : /* OpenTable() */
2872 : /************************************************************************/
2873 :
2874 1493 : bool OGRSQLiteDataSource::OpenTable(const char *pszTableName, bool bIsTable,
2875 : bool bIsVirtualShape, bool bMayEmitError)
2876 :
2877 : {
2878 : /* -------------------------------------------------------------------- */
2879 : /* Create the layer object. */
2880 : /* -------------------------------------------------------------------- */
2881 2986 : auto poLayer = std::make_unique<OGRSQLiteTableLayer>(this);
2882 1493 : if (poLayer->Initialize(pszTableName, bIsTable, bIsVirtualShape, false,
2883 1493 : bMayEmitError) != CE_None)
2884 : {
2885 296 : return false;
2886 : }
2887 :
2888 : /* -------------------------------------------------------------------- */
2889 : /* Add layer to data source layer list. */
2890 : /* -------------------------------------------------------------------- */
2891 1197 : m_apoLayers.push_back(std::move(poLayer));
2892 :
2893 : // Remove in case of error in the schema processing
2894 1197 : if (!DealWithOgrSchemaOpenOption(papszOpenOptions))
2895 : {
2896 4 : m_apoLayers.pop_back();
2897 4 : return false;
2898 : }
2899 :
2900 1193 : return true;
2901 : }
2902 :
2903 : /************************************************************************/
2904 : /* OpenView() */
2905 : /************************************************************************/
2906 :
2907 5 : bool OGRSQLiteDataSource::OpenView(const char *pszViewName,
2908 : const char *pszViewGeometry,
2909 : const char *pszViewRowid,
2910 : const char *pszTableName,
2911 : const char *pszGeometryColumn)
2912 :
2913 : {
2914 : /* -------------------------------------------------------------------- */
2915 : /* Create the layer object. */
2916 : /* -------------------------------------------------------------------- */
2917 10 : auto poLayer = std::make_unique<OGRSQLiteViewLayer>(this);
2918 :
2919 5 : if (poLayer->Initialize(pszViewName, pszViewGeometry, pszViewRowid,
2920 5 : pszTableName, pszGeometryColumn) != CE_None)
2921 : {
2922 0 : return false;
2923 : }
2924 :
2925 : /* -------------------------------------------------------------------- */
2926 : /* Add layer to data source layer list. */
2927 : /* -------------------------------------------------------------------- */
2928 5 : m_apoLayers.push_back(std::move(poLayer));
2929 :
2930 5 : return true;
2931 : }
2932 :
2933 : /************************************************************************/
2934 : /* TestCapability() */
2935 : /************************************************************************/
2936 :
2937 1390 : int OGRSQLiteDataSource::TestCapability(const char *pszCap) const
2938 :
2939 : {
2940 1390 : if (EQUAL(pszCap, ODsCCreateLayer) || EQUAL(pszCap, ODsCDeleteLayer) ||
2941 1175 : EQUAL(pszCap, ODsCCreateGeomFieldAfterCreateLayer) ||
2942 1065 : EQUAL(pszCap, ODsCRandomLayerWrite) ||
2943 1062 : EQUAL(pszCap, GDsCAddRelationship))
2944 328 : return GetUpdate();
2945 1062 : else if (EQUAL(pszCap, ODsCCurveGeometries))
2946 517 : return !m_bIsSpatiaLiteDB;
2947 545 : else if (EQUAL(pszCap, ODsCMeasuredGeometries))
2948 518 : return TRUE;
2949 : else
2950 27 : return OGRSQLiteBaseDataSource::TestCapability(pszCap);
2951 : }
2952 :
2953 : /************************************************************************/
2954 : /* TestCapability() */
2955 : /************************************************************************/
2956 :
2957 354 : int OGRSQLiteBaseDataSource::TestCapability(const char *pszCap) const
2958 : {
2959 354 : if (EQUAL(pszCap, ODsCTransactions))
2960 155 : return true;
2961 199 : else if (EQUAL(pszCap, ODsCZGeometries))
2962 8 : return true;
2963 : else
2964 191 : return GDALPamDataset::TestCapability(pszCap);
2965 : }
2966 :
2967 : /************************************************************************/
2968 : /* GetLayer() */
2969 : /************************************************************************/
2970 :
2971 17336 : const OGRLayer *OGRSQLiteDataSource::GetLayer(int iLayer) const
2972 :
2973 : {
2974 17336 : if (iLayer < 0 || iLayer >= static_cast<int>(m_apoLayers.size()))
2975 10 : return nullptr;
2976 : else
2977 17326 : return m_apoLayers[iLayer].get();
2978 : }
2979 :
2980 : /************************************************************************/
2981 : /* GetLayerByName() */
2982 : /************************************************************************/
2983 :
2984 1448 : OGRLayer *OGRSQLiteDataSource::GetLayerByName(const char *pszLayerName)
2985 :
2986 : {
2987 1448 : OGRLayer *poLayer = GDALDataset::GetLayerByName(pszLayerName);
2988 1448 : if (poLayer != nullptr)
2989 904 : return poLayer;
2990 :
2991 544 : for (auto &poLayerIter : m_apoInvisibleLayers)
2992 : {
2993 0 : if (EQUAL(poLayerIter->GetName(), pszLayerName))
2994 0 : return poLayerIter.get();
2995 : }
2996 :
2997 1088 : std::string osName(pszLayerName);
2998 544 : bool bIsTable = true;
2999 844 : for (int i = 0; i < 2; i++)
3000 : {
3001 844 : char *pszSQL = sqlite3_mprintf("SELECT type FROM sqlite_master "
3002 : "WHERE type IN ('table', 'view') AND "
3003 : "lower(name) = lower('%q')",
3004 : osName.c_str());
3005 844 : int nRowCount = 0;
3006 844 : char **papszResult = nullptr;
3007 844 : CPL_IGNORE_RET_VAL(sqlite3_get_table(hDB, pszSQL, &papszResult,
3008 : &nRowCount, nullptr, nullptr));
3009 844 : if (papszResult && nRowCount == 1 && papszResult[1])
3010 308 : bIsTable = strcmp(papszResult[1], "table") == 0;
3011 844 : sqlite3_free_table(papszResult);
3012 844 : sqlite3_free(pszSQL);
3013 844 : if (i == 0 && nRowCount == 0)
3014 : {
3015 533 : const auto nParenthesis = osName.find('(');
3016 533 : if (nParenthesis != std::string::npos && osName.back() == ')')
3017 : {
3018 300 : osName.resize(nParenthesis);
3019 300 : continue;
3020 : }
3021 : }
3022 544 : break;
3023 : }
3024 :
3025 544 : if (!OpenTable(pszLayerName, bIsTable, /* bIsVirtualShape = */ false,
3026 : /* bMayEmitError = */ false))
3027 297 : return nullptr;
3028 :
3029 247 : poLayer = m_apoLayers.back().get();
3030 247 : CPLErrorReset();
3031 247 : CPLPushErrorHandler(CPLQuietErrorHandler);
3032 247 : poLayer->GetLayerDefn();
3033 247 : CPLPopErrorHandler();
3034 247 : if (CPLGetLastErrorType() != 0)
3035 : {
3036 232 : CPLErrorReset();
3037 232 : m_apoLayers.pop_back();
3038 232 : return nullptr;
3039 : }
3040 :
3041 15 : return poLayer;
3042 : }
3043 :
3044 : /************************************************************************/
3045 : /* IsLayerPrivate() */
3046 : /************************************************************************/
3047 :
3048 8 : bool OGRSQLiteDataSource::IsLayerPrivate(int iLayer) const
3049 : {
3050 8 : if (iLayer < 0 || iLayer >= static_cast<int>(m_apoLayers.size()))
3051 0 : return false;
3052 :
3053 16 : const std::string osName(m_apoLayers[iLayer]->GetName());
3054 16 : const CPLString osLCName(CPLString(osName).tolower());
3055 217 : for (const char *systemTableName : {"spatialindex",
3056 : "geom_cols_ref_sys",
3057 : "geometry_columns",
3058 : "geometry_columns_auth",
3059 : "views_geometry_column",
3060 : "virts_geometry_column",
3061 : "spatial_ref_sys",
3062 : "spatial_ref_sys_all",
3063 : "spatial_ref_sys_aux",
3064 : "sqlite_sequence",
3065 : "tableprefix_metadata",
3066 : "tableprefix_rasters",
3067 : "layer_params",
3068 : "layer_statistics",
3069 : "layer_sub_classes",
3070 : "layer_table_layout",
3071 : "pattern_bitmaps",
3072 : "symbol_bitmaps",
3073 : "project_defs",
3074 : "raster_pyramids",
3075 : "sqlite_stat1",
3076 : "sqlite_stat2",
3077 : "spatialite_history",
3078 : "geometry_columns_field_infos",
3079 : "geometry_columns_statistics",
3080 : "geometry_columns_time",
3081 : "sql_statements_log",
3082 : "vector_layers",
3083 : "vector_layers_auth",
3084 : "vector_layers_field_infos",
3085 : "vector_layers_statistics",
3086 : "views_geometry_columns_auth",
3087 : "views_geometry_columns_field_infos",
3088 : "views_geometry_columns_statistics",
3089 : "virts_geometry_columns_auth",
3090 : "virts_geometry_columns_field_infos",
3091 : "virts_geometry_columns_statistics",
3092 : "virts_layer_statistics",
3093 : "views_layer_statistics",
3094 225 : "elementarygeometries"})
3095 : {
3096 220 : if (osLCName == systemTableName)
3097 3 : return true;
3098 : }
3099 :
3100 5 : return false;
3101 : }
3102 :
3103 : /************************************************************************/
3104 : /* GetLayerByNameNotVisible() */
3105 : /************************************************************************/
3106 :
3107 : OGRLayer *
3108 4 : OGRSQLiteDataSource::GetLayerByNameNotVisible(const char *pszLayerName)
3109 :
3110 : {
3111 : {
3112 4 : OGRLayer *poLayer = GDALDataset::GetLayerByName(pszLayerName);
3113 4 : if (poLayer != nullptr)
3114 2 : return poLayer;
3115 : }
3116 :
3117 2 : for (auto &poLayerIter : m_apoInvisibleLayers)
3118 : {
3119 0 : if (EQUAL(poLayerIter->GetName(), pszLayerName))
3120 0 : return poLayerIter.get();
3121 : }
3122 :
3123 : /* -------------------------------------------------------------------- */
3124 : /* Create the layer object. */
3125 : /* -------------------------------------------------------------------- */
3126 4 : auto poLayer = std::make_unique<OGRSQLiteTableLayer>(this);
3127 2 : if (poLayer->Initialize(pszLayerName, true, false, false,
3128 2 : /* bMayEmitError = */ true) != CE_None)
3129 : {
3130 0 : return nullptr;
3131 : }
3132 2 : CPLErrorReset();
3133 2 : CPLPushErrorHandler(CPLQuietErrorHandler);
3134 2 : poLayer->GetLayerDefn();
3135 2 : CPLPopErrorHandler();
3136 2 : if (CPLGetLastErrorType() != 0)
3137 : {
3138 0 : CPLErrorReset();
3139 0 : return nullptr;
3140 : }
3141 2 : m_apoInvisibleLayers.push_back(std::move(poLayer));
3142 :
3143 2 : return m_apoInvisibleLayers.back().get();
3144 : }
3145 :
3146 : /************************************************************************/
3147 : /* GetLayerWithGetSpatialWhereByName() */
3148 : /************************************************************************/
3149 :
3150 : std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
3151 590 : OGRSQLiteDataSource::GetLayerWithGetSpatialWhereByName(const char *pszName)
3152 : {
3153 : OGRSQLiteLayer *poRet =
3154 590 : cpl::down_cast<OGRSQLiteLayer *>(GetLayerByName(pszName));
3155 590 : return std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>(poRet, poRet);
3156 : }
3157 :
3158 : /************************************************************************/
3159 : /* FlushCache() */
3160 : /************************************************************************/
3161 :
3162 1389 : CPLErr OGRSQLiteDataSource::FlushCache(bool bAtClosing)
3163 : {
3164 1389 : CPLErr eErr = CE_None;
3165 3007 : for (auto &poLayer : m_apoLayers)
3166 : {
3167 1618 : if (poLayer->IsTableLayer())
3168 : {
3169 : OGRSQLiteTableLayer *poTableLayer =
3170 1611 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3171 1611 : if (poTableLayer->RunDeferredCreationIfNecessary() != OGRERR_NONE)
3172 0 : eErr = CE_Failure;
3173 1611 : poTableLayer->CreateSpatialIndexIfNecessary();
3174 : }
3175 : }
3176 1389 : if (GDALDataset::FlushCache(bAtClosing) != CE_None)
3177 0 : eErr = CE_Failure;
3178 1389 : return eErr;
3179 : }
3180 :
3181 : /************************************************************************/
3182 : /* ExecuteSQL() */
3183 : /************************************************************************/
3184 :
3185 : static const char *const apszFuncsWithSideEffects[] = {
3186 : "InitSpatialMetaData", "AddGeometryColumn",
3187 : "RecoverGeometryColumn", "DiscardGeometryColumn",
3188 : "CreateSpatialIndex", "CreateMbrCache",
3189 : "DisableSpatialIndex", "UpdateLayerStatistics",
3190 :
3191 : "ogr_datasource_load_layers"};
3192 :
3193 1297 : OGRLayer *OGRSQLiteDataSource::ExecuteSQL(const char *pszSQLCommand,
3194 : OGRGeometry *poSpatialFilter,
3195 : const char *pszDialect)
3196 :
3197 : {
3198 5393 : for (auto &poLayer : m_apoLayers)
3199 : {
3200 4096 : if (poLayer->IsTableLayer())
3201 : {
3202 : OGRSQLiteTableLayer *poTableLayer =
3203 4092 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3204 4092 : poTableLayer->RunDeferredCreationIfNecessary();
3205 4092 : poTableLayer->CreateSpatialIndexIfNecessary();
3206 : }
3207 : }
3208 :
3209 1297 : if (pszDialect != nullptr && EQUAL(pszDialect, "INDIRECT_SQLITE"))
3210 0 : return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter,
3211 0 : "SQLITE");
3212 1297 : else if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
3213 2 : !EQUAL(pszDialect, "NATIVE") && !EQUAL(pszDialect, "SQLITE"))
3214 :
3215 2 : return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter,
3216 2 : pszDialect);
3217 :
3218 1295 : if (EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like = 0") ||
3219 1294 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like=0") ||
3220 1294 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like =0") ||
3221 1294 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like= 0"))
3222 : {
3223 1 : if (m_poSQLiteModule)
3224 1 : OGR2SQLITE_SetCaseSensitiveLike(m_poSQLiteModule, false);
3225 : }
3226 1294 : else if (EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like = 1") ||
3227 1293 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like=1") ||
3228 1293 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like =1") ||
3229 1293 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like= 1"))
3230 : {
3231 1 : if (m_poSQLiteModule)
3232 1 : OGR2SQLITE_SetCaseSensitiveLike(m_poSQLiteModule, true);
3233 : }
3234 :
3235 : /* -------------------------------------------------------------------- */
3236 : /* Special case DELLAYER: command. */
3237 : /* -------------------------------------------------------------------- */
3238 1295 : if (STARTS_WITH_CI(pszSQLCommand, "DELLAYER:"))
3239 : {
3240 1 : const char *pszLayerName = pszSQLCommand + 9;
3241 :
3242 1 : while (*pszLayerName == ' ')
3243 0 : pszLayerName++;
3244 :
3245 1 : DeleteLayer(pszLayerName);
3246 1 : return nullptr;
3247 : }
3248 :
3249 : /* -------------------------------------------------------------------- */
3250 : /* Special case for SQLITE_HAS_COLUMN_METADATA() */
3251 : /* -------------------------------------------------------------------- */
3252 1294 : if (strcmp(pszSQLCommand, "SQLITE_HAS_COLUMN_METADATA()") == 0)
3253 : {
3254 : #ifdef SQLITE_HAS_COLUMN_METADATA
3255 : return new OGRSQLiteSingleFeatureLayer("SQLITE_HAS_COLUMN_METADATA",
3256 2 : TRUE);
3257 : #else
3258 : return new OGRSQLiteSingleFeatureLayer("SQLITE_HAS_COLUMN_METADATA",
3259 : FALSE);
3260 : #endif
3261 : }
3262 :
3263 : /* -------------------------------------------------------------------- */
3264 : /* In case, this is not a SELECT, invalidate cached feature */
3265 : /* count and extent to be on the safe side. */
3266 : /* -------------------------------------------------------------------- */
3267 1292 : if (EQUAL(pszSQLCommand, "VACUUM"))
3268 : {
3269 1 : int nNeedRefresh = -1;
3270 1 : for (auto &poLayer : m_apoLayers)
3271 : {
3272 1 : if (poLayer->IsTableLayer())
3273 : {
3274 : OGRSQLiteTableLayer *poTableLayer =
3275 1 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3276 1 : if (!(poTableLayer->AreStatisticsValid()) ||
3277 0 : poTableLayer->DoStatisticsNeedToBeFlushed())
3278 : {
3279 1 : nNeedRefresh = FALSE;
3280 1 : break;
3281 : }
3282 0 : else if (nNeedRefresh < 0)
3283 0 : nNeedRefresh = TRUE;
3284 : }
3285 : }
3286 1 : if (nNeedRefresh == TRUE)
3287 : {
3288 0 : for (auto &poLayer : m_apoLayers)
3289 : {
3290 0 : if (poLayer->IsTableLayer())
3291 : {
3292 : OGRSQLiteTableLayer *poTableLayer =
3293 0 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3294 0 : poTableLayer->ForceStatisticsToBeFlushed();
3295 : }
3296 : }
3297 : }
3298 : }
3299 1291 : else if (ProcessTransactionSQL(pszSQLCommand))
3300 : {
3301 251 : return nullptr;
3302 : }
3303 1040 : else if (!STARTS_WITH_CI(pszSQLCommand, "SELECT ") &&
3304 147 : !STARTS_WITH_CI(pszSQLCommand, "CREATE TABLE ") &&
3305 120 : !STARTS_WITH_CI(pszSQLCommand, "PRAGMA "))
3306 : {
3307 162 : for (auto &poLayer : m_apoLayers)
3308 52 : poLayer->InvalidateCachedFeatureCountAndExtent();
3309 : }
3310 :
3311 1041 : m_bLastSQLCommandIsUpdateLayerStatistics =
3312 1041 : EQUAL(pszSQLCommand, "SELECT UpdateLayerStatistics()");
3313 :
3314 : /* -------------------------------------------------------------------- */
3315 : /* Prepare statement. */
3316 : /* -------------------------------------------------------------------- */
3317 2082 : CPLString osSQLCommand = pszSQLCommand;
3318 :
3319 : /* This will speed-up layer creation */
3320 : /* ORDER BY are costly to evaluate and are not necessary to establish */
3321 : /* the layer definition. */
3322 1041 : bool bUseStatementForGetNextFeature = true;
3323 1041 : bool bEmptyLayer = false;
3324 :
3325 4909 : if (osSQLCommand.ifind("SELECT ") == 0 &&
3326 1934 : CPLString(osSQLCommand.substr(1)).ifind("SELECT ") ==
3327 808 : std::string::npos &&
3328 808 : osSQLCommand.ifind(" UNION ") == std::string::npos &&
3329 2742 : osSQLCommand.ifind(" INTERSECT ") == std::string::npos &&
3330 808 : osSQLCommand.ifind(" EXCEPT ") == std::string::npos)
3331 : {
3332 808 : size_t nOrderByPos = osSQLCommand.ifind(" ORDER BY ");
3333 808 : if (nOrderByPos != std::string::npos)
3334 : {
3335 8 : osSQLCommand.resize(nOrderByPos);
3336 8 : bUseStatementForGetNextFeature = false;
3337 : }
3338 : }
3339 :
3340 1041 : const auto nErrorCount = CPLGetErrorCounter();
3341 1041 : sqlite3_stmt *hSQLStmt = prepareSql(GetDB(), osSQLCommand.c_str(),
3342 1041 : static_cast<int>(osSQLCommand.size()));
3343 :
3344 1041 : if (!hSQLStmt)
3345 : {
3346 14 : if (nErrorCount == CPLGetErrorCounter())
3347 : {
3348 11 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
3349 22 : SQLFormatErrorMsgFailedPrepare(
3350 : GetDB(), "In ExecuteSQL(): sqlite3_prepare_v2(): ",
3351 : osSQLCommand.c_str())
3352 : .c_str());
3353 : }
3354 14 : return nullptr;
3355 : }
3356 :
3357 : /* -------------------------------------------------------------------- */
3358 : /* Do we get a resultset? */
3359 : /* -------------------------------------------------------------------- */
3360 1027 : int rc = sqlite3_step(hSQLStmt);
3361 1027 : if (rc != SQLITE_ROW)
3362 : {
3363 302 : if (rc != SQLITE_DONE)
3364 : {
3365 17 : CPLError(CE_Failure, CPLE_AppDefined,
3366 : "In ExecuteSQL(): sqlite3_step(%s):\n %s",
3367 : osSQLCommand.c_str(), sqlite3_errmsg(GetDB()));
3368 :
3369 17 : sqlite3_finalize(hSQLStmt);
3370 17 : return nullptr;
3371 : }
3372 :
3373 285 : if (STARTS_WITH_CI(pszSQLCommand, "CREATE "))
3374 : {
3375 56 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
3376 56 : if (CSLCount(papszTokens) >= 4 &&
3377 66 : EQUAL(papszTokens[1], "VIRTUAL") &&
3378 10 : EQUAL(papszTokens[2], "TABLE"))
3379 : {
3380 10 : OpenVirtualTable(papszTokens[3], pszSQLCommand);
3381 : }
3382 56 : CSLDestroy(papszTokens);
3383 :
3384 56 : sqlite3_finalize(hSQLStmt);
3385 56 : return nullptr;
3386 : }
3387 :
3388 229 : if (!STARTS_WITH_CI(pszSQLCommand, "SELECT "))
3389 : {
3390 62 : sqlite3_finalize(hSQLStmt);
3391 62 : return nullptr;
3392 : }
3393 :
3394 167 : bUseStatementForGetNextFeature = false;
3395 167 : bEmptyLayer = true;
3396 : }
3397 :
3398 : /* -------------------------------------------------------------------- */
3399 : /* Special case for some functions which must be run */
3400 : /* only once */
3401 : /* -------------------------------------------------------------------- */
3402 892 : if (STARTS_WITH_CI(pszSQLCommand, "SELECT "))
3403 : {
3404 8766 : for (unsigned int i = 0; i < sizeof(apszFuncsWithSideEffects) /
3405 : sizeof(apszFuncsWithSideEffects[0]);
3406 : i++)
3407 : {
3408 7898 : if (EQUALN(apszFuncsWithSideEffects[i], pszSQLCommand + 7,
3409 : strlen(apszFuncsWithSideEffects[i])))
3410 : {
3411 20 : if (sqlite3_column_count(hSQLStmt) == 1 &&
3412 10 : sqlite3_column_type(hSQLStmt, 0) == SQLITE_INTEGER)
3413 : {
3414 10 : const int ret = sqlite3_column_int(hSQLStmt, 0);
3415 :
3416 10 : sqlite3_finalize(hSQLStmt);
3417 :
3418 : return new OGRSQLiteSingleFeatureLayer(
3419 10 : apszFuncsWithSideEffects[i], ret);
3420 : }
3421 : }
3422 : }
3423 : }
3424 :
3425 : /* -------------------------------------------------------------------- */
3426 : /* Create layer. */
3427 : /* -------------------------------------------------------------------- */
3428 :
3429 : OGRSQLiteSelectLayer *poLayer = new OGRSQLiteSelectLayer(
3430 : this, pszSQLCommand, hSQLStmt, bUseStatementForGetNextFeature,
3431 882 : bEmptyLayer, true, /*bCanReopenBaseDS=*/true);
3432 :
3433 885 : if (poSpatialFilter != nullptr &&
3434 3 : poLayer->GetLayerDefn()->GetGeomFieldCount() > 0)
3435 3 : poLayer->SetSpatialFilter(0, poSpatialFilter);
3436 :
3437 882 : return poLayer;
3438 : }
3439 :
3440 : /************************************************************************/
3441 : /* ReleaseResultSet() */
3442 : /************************************************************************/
3443 :
3444 896 : void OGRSQLiteDataSource::ReleaseResultSet(OGRLayer *poLayer)
3445 :
3446 : {
3447 896 : delete poLayer;
3448 896 : }
3449 :
3450 : /************************************************************************/
3451 : /* ICreateLayer() */
3452 : /************************************************************************/
3453 :
3454 : OGRLayer *
3455 446 : OGRSQLiteDataSource::ICreateLayer(const char *pszLayerNameIn,
3456 : const OGRGeomFieldDefn *poGeomFieldDefn,
3457 : CSLConstList papszOptions)
3458 :
3459 : {
3460 : /* -------------------------------------------------------------------- */
3461 : /* Verify we are in update mode. */
3462 : /* -------------------------------------------------------------------- */
3463 446 : char *pszLayerName = nullptr;
3464 446 : if (!GetUpdate())
3465 : {
3466 1 : CPLError(CE_Failure, CPLE_NoWriteAccess,
3467 : "Data source %s opened read-only.\n"
3468 : "New layer %s cannot be created.\n",
3469 : m_pszFilename, pszLayerNameIn);
3470 :
3471 1 : return nullptr;
3472 : }
3473 :
3474 445 : const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
3475 : const auto poSRS =
3476 445 : poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
3477 :
3478 445 : if (m_bIsSpatiaLiteDB && eType != wkbNone)
3479 : {
3480 : // We need to catch this right now as AddGeometryColumn does not
3481 : // return an error
3482 147 : OGRwkbGeometryType eFType = wkbFlatten(eType);
3483 147 : if (eFType > wkbGeometryCollection)
3484 : {
3485 0 : CPLError(CE_Failure, CPLE_NotSupported,
3486 : "Cannot create geometry field of type %s",
3487 : OGRToOGCGeomType(eType));
3488 0 : return nullptr;
3489 : }
3490 : }
3491 :
3492 4069 : for (auto &poLayer : m_apoLayers)
3493 : {
3494 3624 : if (poLayer->IsTableLayer())
3495 : {
3496 : OGRSQLiteTableLayer *poTableLayer =
3497 3624 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3498 3624 : poTableLayer->RunDeferredCreationIfNecessary();
3499 : }
3500 : }
3501 :
3502 890 : CPLString osFIDColumnName;
3503 : const char *pszFIDColumnNameIn =
3504 445 : CSLFetchNameValueDef(papszOptions, "FID", "OGC_FID");
3505 445 : if (CPLFetchBool(papszOptions, "LAUNDER", true))
3506 : {
3507 444 : char *pszFIDColumnName = LaunderName(pszFIDColumnNameIn);
3508 444 : osFIDColumnName = pszFIDColumnName;
3509 444 : CPLFree(pszFIDColumnName);
3510 : }
3511 : else
3512 1 : osFIDColumnName = pszFIDColumnNameIn;
3513 :
3514 445 : if (CPLFetchBool(papszOptions, "LAUNDER", true))
3515 444 : pszLayerName = LaunderName(pszLayerNameIn);
3516 : else
3517 1 : pszLayerName = CPLStrdup(pszLayerNameIn);
3518 :
3519 445 : const char *pszGeomFormat = CSLFetchNameValue(papszOptions, "FORMAT");
3520 445 : if (pszGeomFormat == nullptr)
3521 : {
3522 440 : if (!m_bIsSpatiaLiteDB)
3523 287 : pszGeomFormat = "WKB";
3524 : else
3525 153 : pszGeomFormat = "SpatiaLite";
3526 : }
3527 :
3528 445 : if (!EQUAL(pszGeomFormat, "WKT") && !EQUAL(pszGeomFormat, "WKB") &&
3529 155 : !EQUAL(pszGeomFormat, "SpatiaLite"))
3530 : {
3531 1 : CPLError(CE_Failure, CPLE_NotSupported,
3532 : "FORMAT=%s not recognised or supported.", pszGeomFormat);
3533 1 : CPLFree(pszLayerName);
3534 1 : return nullptr;
3535 : }
3536 :
3537 888 : CPLString osGeometryName;
3538 : const char *pszGeometryNameIn =
3539 444 : CSLFetchNameValue(papszOptions, "GEOMETRY_NAME");
3540 444 : if (pszGeometryNameIn == nullptr)
3541 : {
3542 : osGeometryName =
3543 404 : (EQUAL(pszGeomFormat, "WKT")) ? "WKT_GEOMETRY" : "GEOMETRY";
3544 : }
3545 : else
3546 : {
3547 40 : if (CPLFetchBool(papszOptions, "LAUNDER", true))
3548 : {
3549 40 : char *pszGeometryName = LaunderName(pszGeometryNameIn);
3550 40 : osGeometryName = pszGeometryName;
3551 40 : CPLFree(pszGeometryName);
3552 : }
3553 : else
3554 0 : osGeometryName = pszGeometryNameIn;
3555 : }
3556 :
3557 444 : if (m_bIsSpatiaLiteDB && !EQUAL(pszGeomFormat, "SpatiaLite"))
3558 : {
3559 1 : CPLError(CE_Failure, CPLE_NotSupported,
3560 : "FORMAT=%s not supported on a SpatiaLite enabled database.",
3561 : pszGeomFormat);
3562 1 : CPLFree(pszLayerName);
3563 1 : return nullptr;
3564 : }
3565 :
3566 : // Should not happen since a spatialite DB should be opened in
3567 : // read-only mode if libspatialite is not loaded.
3568 443 : if (m_bIsSpatiaLiteDB && !IsSpatialiteLoaded())
3569 : {
3570 0 : CPLError(CE_Failure, CPLE_NotSupported,
3571 : "Creating layers on a SpatiaLite enabled database, "
3572 : "without Spatialite extensions loaded, is not supported.");
3573 0 : CPLFree(pszLayerName);
3574 0 : return nullptr;
3575 : }
3576 :
3577 : /* -------------------------------------------------------------------- */
3578 : /* Do we already have this layer? If so, should we blow it */
3579 : /* away? */
3580 : /* -------------------------------------------------------------------- */
3581 4065 : for (auto &poLayer : m_apoLayers)
3582 : {
3583 3624 : if (EQUAL(pszLayerName, poLayer->GetLayerDefn()->GetName()))
3584 : {
3585 3 : if (CSLFetchNameValue(papszOptions, "OVERWRITE") != nullptr &&
3586 1 : !EQUAL(CSLFetchNameValue(papszOptions, "OVERWRITE"), "NO"))
3587 : {
3588 1 : DeleteLayer(pszLayerName);
3589 1 : break;
3590 : }
3591 : else
3592 : {
3593 1 : CPLError(CE_Failure, CPLE_AppDefined,
3594 : "Layer %s already exists, CreateLayer failed.\n"
3595 : "Use the layer creation option OVERWRITE=YES to "
3596 : "replace it.",
3597 : pszLayerName);
3598 1 : CPLFree(pszLayerName);
3599 1 : return nullptr;
3600 : }
3601 : }
3602 : }
3603 :
3604 : /* -------------------------------------------------------------------- */
3605 : /* Try to get the SRS Id of this spatial reference system, */
3606 : /* adding to the srs table if needed. */
3607 : /* -------------------------------------------------------------------- */
3608 442 : int nSRSId = m_nUndefinedSRID;
3609 442 : const char *pszSRID = CSLFetchNameValue(papszOptions, "SRID");
3610 :
3611 442 : if (pszSRID != nullptr && pszSRID[0] != '\0')
3612 : {
3613 4 : nSRSId = atoi(pszSRID);
3614 4 : if (nSRSId > 0)
3615 : {
3616 4 : OGRSpatialReference *poSRSFetched = FetchSRS(nSRSId);
3617 4 : if (poSRSFetched == nullptr)
3618 : {
3619 2 : CPLError(CE_Warning, CPLE_AppDefined,
3620 : "SRID %d will be used, but no matching SRS is defined "
3621 : "in spatial_ref_sys",
3622 : nSRSId);
3623 : }
3624 4 : }
3625 : }
3626 438 : else if (poSRS != nullptr)
3627 113 : nSRSId = FetchSRSId(poSRS);
3628 :
3629 442 : bool bImmediateSpatialIndexCreation = false;
3630 442 : bool bDeferredSpatialIndexCreation = false;
3631 :
3632 442 : const char *pszSI = CSLFetchNameValue(papszOptions, "SPATIAL_INDEX");
3633 442 : if (m_bHaveGeometryColumns && eType != wkbNone)
3634 : {
3635 0 : if (pszSI != nullptr && CPLTestBool(pszSI) &&
3636 315 : (m_bIsSpatiaLiteDB || EQUAL(pszGeomFormat, "SpatiaLite")) &&
3637 0 : !IsSpatialiteLoaded())
3638 : {
3639 0 : CPLError(CE_Warning, CPLE_OpenFailed,
3640 : "Cannot create a spatial index when Spatialite extensions "
3641 : "are not loaded.");
3642 : }
3643 :
3644 : #ifdef HAVE_SPATIALITE
3645 : /* Only if linked against SpatiaLite and the datasource was created as a
3646 : * SpatiaLite DB */
3647 315 : if (m_bIsSpatiaLiteDB && IsSpatialiteLoaded())
3648 : {
3649 146 : if (pszSI != nullptr && EQUAL(pszSI, "IMMEDIATE"))
3650 : {
3651 0 : bImmediateSpatialIndexCreation = true;
3652 : }
3653 146 : else if (pszSI == nullptr || CPLTestBool(pszSI))
3654 : {
3655 146 : bDeferredSpatialIndexCreation = true;
3656 : }
3657 : }
3658 : #endif
3659 : }
3660 127 : else if (m_bHaveGeometryColumns)
3661 : {
3662 : #ifdef HAVE_SPATIALITE
3663 118 : if (m_bIsSpatiaLiteDB && IsSpatialiteLoaded() &&
3664 0 : (pszSI == nullptr || CPLTestBool(pszSI)))
3665 7 : bDeferredSpatialIndexCreation = true;
3666 : #endif
3667 : }
3668 :
3669 : /* -------------------------------------------------------------------- */
3670 : /* Create the layer object. */
3671 : /* -------------------------------------------------------------------- */
3672 884 : auto poLayer = std::make_unique<OGRSQLiteTableLayer>(this);
3673 :
3674 442 : poLayer->Initialize(pszLayerName, true, false, true,
3675 : /* bMayEmitError = */ false);
3676 442 : OGRSpatialReference *poSRSClone = nullptr;
3677 442 : if (poSRS)
3678 : {
3679 113 : poSRSClone = poSRS->Clone();
3680 113 : poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
3681 : }
3682 442 : poLayer->SetCreationParameters(osFIDColumnName, eType, pszGeomFormat,
3683 : osGeometryName, poSRSClone, nSRSId);
3684 442 : if (poSRSClone)
3685 113 : poSRSClone->Release();
3686 :
3687 442 : poLayer->InitFeatureCount();
3688 442 : poLayer->SetLaunderFlag(CPLFetchBool(papszOptions, "LAUNDER", true));
3689 442 : if (CPLFetchBool(papszOptions, "COMPRESS_GEOM", false))
3690 47 : poLayer->SetUseCompressGeom(true);
3691 442 : if (bImmediateSpatialIndexCreation)
3692 0 : poLayer->CreateSpatialIndex(0);
3693 442 : else if (bDeferredSpatialIndexCreation)
3694 153 : poLayer->SetDeferredSpatialIndexCreation(true);
3695 442 : poLayer->SetCompressedColumns(
3696 : CSLFetchNameValue(papszOptions, "COMPRESS_COLUMNS"));
3697 442 : poLayer->SetStrictFlag(CPLFetchBool(papszOptions, "STRICT", false));
3698 :
3699 442 : CPLFree(pszLayerName);
3700 :
3701 : /* -------------------------------------------------------------------- */
3702 : /* Add layer to data source layer list. */
3703 : /* -------------------------------------------------------------------- */
3704 442 : m_apoLayers.push_back(std::move(poLayer));
3705 :
3706 442 : return m_apoLayers.back().get();
3707 : }
3708 :
3709 : /************************************************************************/
3710 : /* LaunderName() */
3711 : /************************************************************************/
3712 :
3713 2199 : char *OGRSQLiteDataSource::LaunderName(const char *pszSrcName)
3714 :
3715 : {
3716 2199 : char *pszSafeName = CPLStrdup(pszSrcName);
3717 22547 : for (int i = 0; pszSafeName[i] != '\0'; i++)
3718 : {
3719 20348 : pszSafeName[i] = static_cast<char>(
3720 20348 : CPLTolower(static_cast<unsigned char>(pszSafeName[i])));
3721 20348 : if (pszSafeName[i] == '\'' || pszSafeName[i] == '-' ||
3722 20348 : pszSafeName[i] == '#')
3723 0 : pszSafeName[i] = '_';
3724 : }
3725 :
3726 2199 : return pszSafeName;
3727 : }
3728 :
3729 : /************************************************************************/
3730 : /* DeleteLayer() */
3731 : /************************************************************************/
3732 :
3733 2 : void OGRSQLiteDataSource::DeleteLayer(const char *pszLayerName)
3734 :
3735 : {
3736 : /* -------------------------------------------------------------------- */
3737 : /* Verify we are in update mode. */
3738 : /* -------------------------------------------------------------------- */
3739 2 : if (!GetUpdate())
3740 : {
3741 0 : CPLError(CE_Failure, CPLE_NoWriteAccess,
3742 : "Data source %s opened read-only.\n"
3743 : "Layer %s cannot be deleted.\n",
3744 : m_pszFilename, pszLayerName);
3745 :
3746 0 : return;
3747 : }
3748 :
3749 : /* -------------------------------------------------------------------- */
3750 : /* Try to find layer. */
3751 : /* -------------------------------------------------------------------- */
3752 2 : int iLayer = 0; // Used after for.
3753 :
3754 2 : for (; iLayer < static_cast<int>(m_apoLayers.size()); iLayer++)
3755 : {
3756 2 : if (EQUAL(pszLayerName, m_apoLayers[iLayer]->GetLayerDefn()->GetName()))
3757 2 : break;
3758 : }
3759 :
3760 2 : if (iLayer == static_cast<int>(m_apoLayers.size()))
3761 : {
3762 0 : CPLError(
3763 : CE_Failure, CPLE_AppDefined,
3764 : "Attempt to delete layer '%s', but this layer is not known to OGR.",
3765 : pszLayerName);
3766 0 : return;
3767 : }
3768 :
3769 2 : DeleteLayer(iLayer);
3770 : }
3771 :
3772 : /************************************************************************/
3773 : /* DeleteLayer() */
3774 : /************************************************************************/
3775 :
3776 34 : OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
3777 : {
3778 34 : if (iLayer < 0 || iLayer >= static_cast<int>(m_apoLayers.size()))
3779 : {
3780 0 : CPLError(CE_Failure, CPLE_AppDefined,
3781 : "Layer %d not in legal range of 0 to %d.", iLayer,
3782 0 : static_cast<int>(m_apoLayers.size()) - 1);
3783 0 : return OGRERR_FAILURE;
3784 : }
3785 :
3786 68 : CPLString osLayerName = GetLayer(iLayer)->GetName();
3787 68 : CPLString osGeometryColumn = GetLayer(iLayer)->GetGeometryColumn();
3788 :
3789 : /* -------------------------------------------------------------------- */
3790 : /* Blow away our OGR structures related to the layer. This is */
3791 : /* pretty dangerous if anything has a reference to this layer! */
3792 : /* -------------------------------------------------------------------- */
3793 34 : CPLDebug("OGR_SQLITE", "DeleteLayer(%s)", osLayerName.c_str());
3794 :
3795 34 : m_apoLayers.erase(m_apoLayers.begin() + iLayer);
3796 :
3797 : /* -------------------------------------------------------------------- */
3798 : /* Remove from the database. */
3799 : /* -------------------------------------------------------------------- */
3800 68 : CPLString osEscapedLayerName = SQLEscapeLiteral(osLayerName);
3801 34 : const char *pszEscapedLayerName = osEscapedLayerName.c_str();
3802 : const char *pszGeometryColumn =
3803 34 : osGeometryColumn.size() ? osGeometryColumn.c_str() : nullptr;
3804 :
3805 34 : if (SQLCommand(hDB, CPLSPrintf("DROP TABLE '%s'", pszEscapedLayerName)) !=
3806 : OGRERR_NONE)
3807 : {
3808 0 : return OGRERR_FAILURE;
3809 : }
3810 :
3811 : /* -------------------------------------------------------------------- */
3812 : /* Drop from geometry_columns table. */
3813 : /* -------------------------------------------------------------------- */
3814 34 : if (m_bHaveGeometryColumns)
3815 : {
3816 34 : CPLString osCommand;
3817 :
3818 : osCommand.Printf(
3819 : "DELETE FROM geometry_columns WHERE f_table_name = '%s'",
3820 34 : pszEscapedLayerName);
3821 :
3822 34 : if (SQLCommand(hDB, osCommand) != OGRERR_NONE)
3823 : {
3824 0 : return OGRERR_FAILURE;
3825 : }
3826 :
3827 : /* --------------------------------------------------------------------
3828 : */
3829 : /* Drop spatialite spatial index tables */
3830 : /* --------------------------------------------------------------------
3831 : */
3832 34 : if (m_bIsSpatiaLiteDB && pszGeometryColumn)
3833 : {
3834 : osCommand.Printf("DROP TABLE 'idx_%s_%s'", pszEscapedLayerName,
3835 15 : SQLEscapeLiteral(pszGeometryColumn).c_str());
3836 15 : CPL_IGNORE_RET_VAL(
3837 15 : sqlite3_exec(hDB, osCommand, nullptr, nullptr, nullptr));
3838 :
3839 : osCommand.Printf("DROP TABLE 'idx_%s_%s_node'", pszEscapedLayerName,
3840 15 : SQLEscapeLiteral(pszGeometryColumn).c_str());
3841 15 : CPL_IGNORE_RET_VAL(
3842 15 : sqlite3_exec(hDB, osCommand, nullptr, nullptr, nullptr));
3843 :
3844 : osCommand.Printf("DROP TABLE 'idx_%s_%s_parent'",
3845 : pszEscapedLayerName,
3846 15 : SQLEscapeLiteral(pszGeometryColumn).c_str());
3847 15 : CPL_IGNORE_RET_VAL(
3848 15 : sqlite3_exec(hDB, osCommand, nullptr, nullptr, nullptr));
3849 :
3850 : osCommand.Printf("DROP TABLE 'idx_%s_%s_rowid'",
3851 : pszEscapedLayerName,
3852 15 : SQLEscapeLiteral(pszGeometryColumn).c_str());
3853 15 : CPL_IGNORE_RET_VAL(
3854 15 : sqlite3_exec(hDB, osCommand, nullptr, nullptr, nullptr));
3855 : }
3856 : }
3857 34 : return OGRERR_NONE;
3858 : }
3859 :
3860 : /************************************************************************/
3861 : /* StartTransaction() */
3862 : /* */
3863 : /* Should only be called by user code. Not driver internals. */
3864 : /************************************************************************/
3865 :
3866 507 : OGRErr OGRSQLiteBaseDataSource::StartTransaction(CPL_UNUSED int bForce)
3867 : {
3868 507 : if (m_bUserTransactionActive || m_nSoftTransactionLevel != 0)
3869 : {
3870 21 : CPLError(CE_Failure, CPLE_AppDefined,
3871 : "Transaction already established");
3872 21 : return OGRERR_FAILURE;
3873 : }
3874 :
3875 : // Check if we are in a SAVEPOINT transaction
3876 486 : if (m_aosSavepoints.size() > 0)
3877 : {
3878 0 : CPLError(CE_Failure, CPLE_AppDefined,
3879 : "Cannot start a transaction within a SAVEPOINT");
3880 0 : return OGRERR_FAILURE;
3881 : }
3882 :
3883 486 : OGRErr eErr = SoftStartTransaction();
3884 486 : if (eErr != OGRERR_NONE)
3885 0 : return eErr;
3886 :
3887 486 : m_bUserTransactionActive = true;
3888 486 : return OGRERR_NONE;
3889 : }
3890 :
3891 88 : OGRErr OGRSQLiteDataSource::StartTransaction(int bForce)
3892 : {
3893 163 : for (auto &poLayer : m_apoLayers)
3894 : {
3895 75 : if (poLayer->IsTableLayer())
3896 : {
3897 : OGRSQLiteTableLayer *poTableLayer =
3898 75 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3899 75 : poTableLayer->RunDeferredCreationIfNecessary();
3900 : }
3901 : }
3902 :
3903 88 : return OGRSQLiteBaseDataSource::StartTransaction(bForce);
3904 : }
3905 :
3906 : /************************************************************************/
3907 : /* CommitTransaction() */
3908 : /* */
3909 : /* Should only be called by user code. Not driver internals. */
3910 : /************************************************************************/
3911 :
3912 448 : OGRErr OGRSQLiteBaseDataSource::CommitTransaction()
3913 : {
3914 448 : if (!m_bUserTransactionActive && !m_bImplicitTransactionOpened)
3915 : {
3916 8 : CPLError(CE_Failure, CPLE_AppDefined, "Transaction not established");
3917 8 : return OGRERR_FAILURE;
3918 : }
3919 :
3920 440 : m_bUserTransactionActive = false;
3921 440 : m_bImplicitTransactionOpened = false;
3922 440 : CPLAssert(m_nSoftTransactionLevel == 1);
3923 440 : return SoftCommitTransaction();
3924 : }
3925 :
3926 74 : OGRErr OGRSQLiteDataSource::CommitTransaction()
3927 :
3928 : {
3929 74 : if (m_nSoftTransactionLevel == 1)
3930 : {
3931 247 : for (auto &poLayer : m_apoLayers)
3932 : {
3933 175 : if (poLayer->IsTableLayer())
3934 : {
3935 : OGRSQLiteTableLayer *poTableLayer =
3936 175 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3937 175 : poTableLayer->RunDeferredCreationIfNecessary();
3938 : }
3939 : }
3940 : }
3941 :
3942 74 : return OGRSQLiteBaseDataSource::CommitTransaction();
3943 : }
3944 :
3945 : /************************************************************************/
3946 : /* RollbackTransaction() */
3947 : /* */
3948 : /* Should only be called by user code. Not driver internals. */
3949 : /************************************************************************/
3950 :
3951 58 : OGRErr OGRSQLiteBaseDataSource::RollbackTransaction()
3952 : {
3953 58 : if (!m_bUserTransactionActive)
3954 : {
3955 3 : CPLError(CE_Failure, CPLE_AppDefined, "Transaction not established");
3956 3 : return OGRERR_FAILURE;
3957 : }
3958 :
3959 55 : m_bUserTransactionActive = false;
3960 55 : CPLAssert(m_nSoftTransactionLevel == 1);
3961 :
3962 55 : return SoftRollbackTransaction();
3963 : }
3964 :
3965 21 : OGRErr OGRSQLiteDataSource::RollbackTransaction()
3966 :
3967 : {
3968 21 : if (m_nSoftTransactionLevel == 1)
3969 : {
3970 38 : for (auto &poLayer : m_apoLayers)
3971 : {
3972 19 : if (poLayer->IsTableLayer())
3973 : {
3974 : OGRSQLiteTableLayer *poTableLayer =
3975 19 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3976 19 : poTableLayer->RunDeferredCreationIfNecessary();
3977 : }
3978 : }
3979 :
3980 38 : for (auto &poLayer : m_apoLayers)
3981 : {
3982 19 : poLayer->InvalidateCachedFeatureCountAndExtent();
3983 19 : poLayer->ResetReading();
3984 : }
3985 : }
3986 :
3987 21 : return OGRSQLiteBaseDataSource::RollbackTransaction();
3988 : }
3989 :
3990 1737 : bool OGRSQLiteBaseDataSource::IsInTransaction() const
3991 : {
3992 1737 : return m_nSoftTransactionLevel > 0;
3993 : }
3994 :
3995 : /************************************************************************/
3996 : /* SoftStartTransaction() */
3997 : /* */
3998 : /* Create a transaction scope. If we already have a */
3999 : /* transaction active this isn't a real transaction, but just */
4000 : /* an increment to the scope count. */
4001 : /************************************************************************/
4002 :
4003 3897 : OGRErr OGRSQLiteBaseDataSource::SoftStartTransaction()
4004 :
4005 : {
4006 3897 : m_nSoftTransactionLevel++;
4007 :
4008 3897 : OGRErr eErr = OGRERR_NONE;
4009 3897 : if (m_nSoftTransactionLevel == 1)
4010 : {
4011 6713 : for (auto *poLayer : GetLayers())
4012 : {
4013 3008 : poLayer->PrepareStartTransaction();
4014 : }
4015 :
4016 3705 : eErr = DoTransactionCommand("BEGIN");
4017 : }
4018 :
4019 : // CPLDebug("SQLite", "%p->SoftStartTransaction() : %d",
4020 : // this, nSoftTransactionLevel);
4021 :
4022 3897 : return eErr;
4023 : }
4024 :
4025 : /************************************************************************/
4026 : /* SoftCommitTransaction() */
4027 : /* */
4028 : /* Commit the current transaction if we are at the outer */
4029 : /* scope. */
4030 : /************************************************************************/
4031 :
4032 3840 : OGRErr OGRSQLiteBaseDataSource::SoftCommitTransaction()
4033 :
4034 : {
4035 : // CPLDebug("SQLite", "%p->SoftCommitTransaction() : %d",
4036 : // this, nSoftTransactionLevel);
4037 :
4038 3840 : if (m_nSoftTransactionLevel <= 0)
4039 : {
4040 0 : CPLAssert(false);
4041 : return OGRERR_FAILURE;
4042 : }
4043 :
4044 3840 : OGRErr eErr = OGRERR_NONE;
4045 3840 : m_nSoftTransactionLevel--;
4046 3840 : if (m_nSoftTransactionLevel == 0)
4047 : {
4048 3648 : eErr = DoTransactionCommand("COMMIT");
4049 : }
4050 :
4051 3840 : return eErr;
4052 : }
4053 :
4054 : /************************************************************************/
4055 : /* SoftRollbackTransaction() */
4056 : /* */
4057 : /* Do a rollback of the current transaction if we are at the 1st */
4058 : /* level */
4059 : /************************************************************************/
4060 :
4061 126 : OGRErr OGRSQLiteBaseDataSource::SoftRollbackTransaction()
4062 :
4063 : {
4064 : // CPLDebug("SQLite", "%p->SoftRollbackTransaction() : %d",
4065 : // this, nSoftTransactionLevel);
4066 :
4067 126 : while (!m_aosSavepoints.empty())
4068 : {
4069 28 : if (RollbackToSavepoint(m_aosSavepoints.back()) != OGRERR_NONE)
4070 : {
4071 0 : return OGRERR_FAILURE;
4072 : }
4073 28 : m_aosSavepoints.pop_back();
4074 : }
4075 :
4076 98 : if (m_nSoftTransactionLevel <= 0)
4077 : {
4078 0 : CPLAssert(false);
4079 : return OGRERR_FAILURE;
4080 : }
4081 :
4082 98 : OGRErr eErr = OGRERR_NONE;
4083 98 : m_nSoftTransactionLevel--;
4084 98 : if (m_nSoftTransactionLevel == 0)
4085 : {
4086 98 : eErr = DoTransactionCommand("ROLLBACK");
4087 98 : if (eErr == OGRERR_NONE)
4088 : {
4089 190 : for (auto *poLayer : GetLayers())
4090 : {
4091 92 : poLayer->FinishRollbackTransaction("");
4092 : }
4093 : }
4094 : }
4095 :
4096 98 : return eErr;
4097 : }
4098 :
4099 293 : OGRErr OGRSQLiteBaseDataSource::StartSavepoint(const std::string &osName)
4100 : {
4101 :
4102 : // A SAVEPOINT implicitly starts a transaction, let's fake one
4103 293 : if (!IsInTransaction())
4104 : {
4105 52 : m_bImplicitTransactionOpened = true;
4106 52 : m_nSoftTransactionLevel++;
4107 104 : for (auto *poLayer : GetLayers())
4108 : {
4109 52 : poLayer->PrepareStartTransaction();
4110 : }
4111 : }
4112 :
4113 293 : const std::string osCommand = "SAVEPOINT " + osName;
4114 293 : const auto eErr = DoTransactionCommand(osCommand.c_str());
4115 :
4116 293 : if (eErr == OGRERR_NONE)
4117 : {
4118 293 : m_aosSavepoints.push_back(osName);
4119 : }
4120 :
4121 586 : return eErr;
4122 : }
4123 :
4124 32 : OGRErr OGRSQLiteBaseDataSource::ReleaseSavepoint(const std::string &osName)
4125 : {
4126 64 : if (m_aosSavepoints.empty() ||
4127 32 : std::find(m_aosSavepoints.cbegin(), m_aosSavepoints.cend(), osName) ==
4128 64 : m_aosSavepoints.cend())
4129 : {
4130 0 : CPLError(CE_Failure, CPLE_AppDefined, "Savepoint %s not found",
4131 : osName.c_str());
4132 0 : return OGRERR_FAILURE;
4133 : }
4134 :
4135 32 : const std::string osCommand = "RELEASE SAVEPOINT " + osName;
4136 32 : const auto eErr = DoTransactionCommand(osCommand.c_str());
4137 :
4138 32 : if (eErr == OGRERR_NONE)
4139 : {
4140 : // If the savepoint is the outer most, this is the same as COMMIT
4141 : // and the transaction is closed
4142 48 : if (m_bImplicitTransactionOpened &&
4143 16 : m_aosSavepoints.front().compare(osName) == 0)
4144 : {
4145 4 : m_bImplicitTransactionOpened = false;
4146 4 : m_bUserTransactionActive = false;
4147 4 : m_nSoftTransactionLevel = 0;
4148 4 : m_aosSavepoints.clear();
4149 : }
4150 : else
4151 : {
4152 : // Find all savepoints up to the target one and remove them
4153 64 : while (!m_aosSavepoints.empty() && m_aosSavepoints.back() != osName)
4154 : {
4155 36 : m_aosSavepoints.pop_back();
4156 : }
4157 28 : if (!m_aosSavepoints.empty()) // should always be true
4158 : {
4159 28 : m_aosSavepoints.pop_back();
4160 : }
4161 : }
4162 : }
4163 32 : return eErr;
4164 : }
4165 :
4166 117 : OGRErr OGRSQLiteBaseDataSource::RollbackToSavepoint(const std::string &osName)
4167 : {
4168 226 : if (m_aosSavepoints.empty() ||
4169 109 : std::find(m_aosSavepoints.cbegin(), m_aosSavepoints.cend(), osName) ==
4170 226 : m_aosSavepoints.cend())
4171 : {
4172 36 : CPLError(CE_Failure, CPLE_AppDefined, "Savepoint %s not found",
4173 : osName.c_str());
4174 36 : return OGRERR_FAILURE;
4175 : }
4176 :
4177 81 : const std::string osCommand = "ROLLBACK TO SAVEPOINT " + osName;
4178 81 : const auto eErr = DoTransactionCommand(osCommand.c_str());
4179 :
4180 81 : if (eErr == OGRERR_NONE)
4181 : {
4182 :
4183 : // The target savepoint should become the last one in the list
4184 : // and does not need to be removed because ROLLBACK TO SAVEPOINT
4185 137 : while (!m_aosSavepoints.empty() && m_aosSavepoints.back() != osName)
4186 : {
4187 56 : m_aosSavepoints.pop_back();
4188 : }
4189 : }
4190 :
4191 162 : for (int i = 0; i < GetLayerCount(); i++)
4192 : {
4193 81 : OGRLayer *poLayer = GetLayer(i);
4194 81 : poLayer->FinishRollbackTransaction(osName);
4195 : }
4196 :
4197 81 : return eErr;
4198 : }
4199 :
4200 : /************************************************************************/
4201 : /* ProcessTransactionSQL() */
4202 : /************************************************************************/
4203 6988 : bool OGRSQLiteBaseDataSource::ProcessTransactionSQL(
4204 : const std::string &osSQLCommand)
4205 : {
4206 6988 : bool retVal = true;
4207 :
4208 6988 : if (EQUAL(osSQLCommand.c_str(), "BEGIN"))
4209 : {
4210 28 : SoftStartTransaction();
4211 : }
4212 6960 : else if (EQUAL(osSQLCommand.c_str(), "COMMIT"))
4213 : {
4214 30 : SoftCommitTransaction();
4215 : }
4216 6930 : else if (EQUAL(osSQLCommand.c_str(), "ROLLBACK"))
4217 : {
4218 32 : SoftRollbackTransaction();
4219 : }
4220 6898 : else if (STARTS_WITH_CI(osSQLCommand.c_str(), "SAVEPOINT"))
4221 : {
4222 586 : const CPLStringList aosTokens(SQLTokenize(osSQLCommand.c_str()));
4223 293 : if (aosTokens.size() == 2)
4224 : {
4225 293 : const char *pszSavepointName = aosTokens[1];
4226 293 : StartSavepoint(pszSavepointName);
4227 : }
4228 : else
4229 : {
4230 0 : retVal = false;
4231 : }
4232 : }
4233 6605 : else if (STARTS_WITH_CI(osSQLCommand.c_str(), "RELEASE"))
4234 : {
4235 64 : const CPLStringList aosTokens(SQLTokenize(osSQLCommand.c_str()));
4236 32 : if (aosTokens.size() == 2)
4237 : {
4238 32 : const char *pszSavepointName = aosTokens[1];
4239 32 : ReleaseSavepoint(pszSavepointName);
4240 : }
4241 0 : else if (aosTokens.size() == 3 && EQUAL(aosTokens[1], "SAVEPOINT"))
4242 : {
4243 0 : const char *pszSavepointName = aosTokens[2];
4244 0 : ReleaseSavepoint(pszSavepointName);
4245 : }
4246 : else
4247 : {
4248 0 : retVal = false;
4249 : }
4250 : }
4251 6573 : else if (STARTS_WITH_CI(osSQLCommand.c_str(), "ROLLBACK"))
4252 : {
4253 178 : const CPLStringList aosTokens(SQLTokenize(osSQLCommand.c_str()));
4254 89 : if (aosTokens.size() == 2)
4255 : {
4256 56 : if (EQUAL(aosTokens[1], "TRANSACTION"))
4257 : {
4258 0 : SoftRollbackTransaction();
4259 : }
4260 : else
4261 : {
4262 56 : const char *pszSavepointName = aosTokens[1];
4263 56 : RollbackToSavepoint(pszSavepointName);
4264 : }
4265 : }
4266 33 : else if (aosTokens.size() > 1) // Savepoint name is last token
4267 : {
4268 33 : const char *pszSavepointName = aosTokens[aosTokens.size() - 1];
4269 33 : RollbackToSavepoint(pszSavepointName);
4270 : }
4271 : }
4272 : else
4273 : {
4274 6484 : retVal = false;
4275 : }
4276 :
4277 6988 : return retVal;
4278 : }
4279 :
4280 : /************************************************************************/
4281 : /* DoTransactionCommand() */
4282 : /************************************************************************/
4283 :
4284 7857 : OGRErr OGRSQLiteBaseDataSource::DoTransactionCommand(const char *pszCommand)
4285 :
4286 : {
4287 : #ifdef DEBUG
4288 7857 : CPLDebug("OGR_SQLITE", "%s Transaction", pszCommand);
4289 : #endif
4290 :
4291 7857 : return SQLCommand(hDB, pszCommand);
4292 : }
4293 :
4294 : /************************************************************************/
4295 : /* GetSRTEXTColName() */
4296 : /************************************************************************/
4297 :
4298 36 : const char *OGRSQLiteDataSource::GetSRTEXTColName()
4299 : {
4300 36 : if (!m_bIsSpatiaLiteDB || m_bSpatialite4Layout)
4301 28 : return "srtext";
4302 :
4303 : // Testing for SRS_WKT column presence.
4304 8 : bool bHasSrsWkt = false;
4305 8 : char **papszResult = nullptr;
4306 8 : int nRowCount = 0;
4307 8 : int nColCount = 0;
4308 8 : char *pszErrMsg = nullptr;
4309 : const int rc =
4310 8 : sqlite3_get_table(hDB, "PRAGMA table_info(spatial_ref_sys)",
4311 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
4312 :
4313 8 : if (rc == SQLITE_OK)
4314 : {
4315 56 : for (int iRow = 1; iRow <= nRowCount; iRow++)
4316 : {
4317 48 : if (EQUAL("srs_wkt", papszResult[(iRow * nColCount) + 1]))
4318 8 : bHasSrsWkt = true;
4319 : }
4320 8 : sqlite3_free_table(papszResult);
4321 : }
4322 : else
4323 : {
4324 0 : sqlite3_free(pszErrMsg);
4325 : }
4326 :
4327 8 : return bHasSrsWkt ? "srs_wkt" : nullptr;
4328 : }
4329 :
4330 : /************************************************************************/
4331 : /* AddSRIDToCache() */
4332 : /* */
4333 : /* Note: this will not add a reference on the poSRS object. Make */
4334 : /* sure it is freshly created, or add a reference yourself if not. */
4335 : /************************************************************************/
4336 :
4337 : OGRSpatialReference *
4338 232 : OGRSQLiteDataSource::AddSRIDToCache(int nId,
4339 : OGRSpatialReferenceRefCountedPtr poSRS)
4340 : {
4341 : /* -------------------------------------------------------------------- */
4342 : /* Add to the cache. */
4343 : /* -------------------------------------------------------------------- */
4344 232 : auto oIter = m_oSRSCache.emplace(nId, std::move(poSRS)).first;
4345 464 : return oIter->second.get();
4346 : }
4347 :
4348 : /************************************************************************/
4349 : /* FetchSRSId() */
4350 : /* */
4351 : /* Fetch the id corresponding to an SRS, and if not found, add */
4352 : /* it to the table. */
4353 : /************************************************************************/
4354 :
4355 283 : int OGRSQLiteDataSource::FetchSRSId(const OGRSpatialReference *poSRSIn)
4356 :
4357 : {
4358 283 : int nSRSId = m_nUndefinedSRID;
4359 283 : if (poSRSIn == nullptr)
4360 0 : return nSRSId;
4361 :
4362 : /* -------------------------------------------------------------------- */
4363 : /* First, we look through our SRID cache, is it there? */
4364 : /* -------------------------------------------------------------------- */
4365 492 : for (const auto &pair : m_oSRSCache)
4366 : {
4367 209 : if (pair.second.get() == poSRSIn)
4368 0 : return pair.first;
4369 : }
4370 383 : for (const auto &pair : m_oSRSCache)
4371 : {
4372 209 : if (pair.second != nullptr && pair.second->IsSame(poSRSIn))
4373 109 : return pair.first;
4374 : }
4375 :
4376 : /* -------------------------------------------------------------------- */
4377 : /* Build a copy since we may call AutoIdentifyEPSG() */
4378 : /* -------------------------------------------------------------------- */
4379 348 : auto poSRS = OGRSpatialReferenceRefCountedPtr::makeClone(poSRSIn);
4380 :
4381 174 : const char *pszAuthorityName = poSRS->GetAuthorityName();
4382 174 : const char *pszAuthorityCode = nullptr;
4383 :
4384 174 : if (pszAuthorityName == nullptr || strlen(pszAuthorityName) == 0)
4385 : {
4386 : /* --------------------------------------------------------------------
4387 : */
4388 : /* Try to identify an EPSG code */
4389 : /* --------------------------------------------------------------------
4390 : */
4391 3 : poSRS->AutoIdentifyEPSG();
4392 :
4393 3 : pszAuthorityName = poSRS->GetAuthorityName();
4394 3 : if (pszAuthorityName != nullptr && EQUAL(pszAuthorityName, "EPSG"))
4395 : {
4396 0 : pszAuthorityCode = poSRS->GetAuthorityCode();
4397 0 : if (pszAuthorityCode != nullptr && strlen(pszAuthorityCode) > 0)
4398 : {
4399 : /* Import 'clean' SRS */
4400 0 : poSRS->importFromEPSG(atoi(pszAuthorityCode));
4401 :
4402 0 : pszAuthorityName = poSRS->GetAuthorityName();
4403 0 : pszAuthorityCode = poSRS->GetAuthorityCode();
4404 : }
4405 : }
4406 : }
4407 :
4408 : /* -------------------------------------------------------------------- */
4409 : /* Check whether the EPSG authority code is already mapped to a */
4410 : /* SRS ID. */
4411 : /* -------------------------------------------------------------------- */
4412 174 : char *pszErrMsg = nullptr;
4413 348 : CPLString osCommand;
4414 174 : char **papszResult = nullptr;
4415 174 : int nRowCount = 0;
4416 174 : int nColCount = 0;
4417 :
4418 174 : if (pszAuthorityName != nullptr && strlen(pszAuthorityName) > 0)
4419 : {
4420 171 : pszAuthorityCode = poSRS->GetAuthorityCode();
4421 :
4422 171 : if (pszAuthorityCode != nullptr && strlen(pszAuthorityCode) > 0)
4423 : {
4424 : // XXX: We are using case insensitive comparison for "auth_name"
4425 : // values, because there are variety of options exist. By default
4426 : // the driver uses 'EPSG' in upper case, but SpatiaLite extension
4427 : // uses 'epsg' in lower case.
4428 : osCommand.Printf(
4429 : "SELECT srid FROM spatial_ref_sys WHERE "
4430 : "auth_name = '%s' COLLATE NOCASE AND auth_srid = '%s' "
4431 : "LIMIT 2",
4432 171 : pszAuthorityName, pszAuthorityCode);
4433 :
4434 171 : int rc = sqlite3_get_table(hDB, osCommand, &papszResult, &nRowCount,
4435 : &nColCount, &pszErrMsg);
4436 171 : if (rc != SQLITE_OK)
4437 : {
4438 : /* Retry without COLLATE NOCASE which may not be understood by
4439 : * older sqlite3 */
4440 0 : sqlite3_free(pszErrMsg);
4441 :
4442 : osCommand.Printf("SELECT srid FROM spatial_ref_sys WHERE "
4443 : "auth_name = '%s' AND auth_srid = '%s'",
4444 0 : pszAuthorityName, pszAuthorityCode);
4445 :
4446 0 : rc = sqlite3_get_table(hDB, osCommand, &papszResult, &nRowCount,
4447 : &nColCount, &pszErrMsg);
4448 :
4449 : /* Retry in lower case for SpatiaLite */
4450 0 : if (rc != SQLITE_OK)
4451 : {
4452 0 : sqlite3_free(pszErrMsg);
4453 : }
4454 0 : else if (nRowCount == 0 &&
4455 0 : strcmp(pszAuthorityName, "EPSG") == 0)
4456 : {
4457 : /* If it is in upper case, look for lower case */
4458 0 : sqlite3_free_table(papszResult);
4459 :
4460 : osCommand.Printf("SELECT srid FROM spatial_ref_sys WHERE "
4461 : "auth_name = 'epsg' AND auth_srid = '%s' "
4462 : "LIMIT 2",
4463 0 : pszAuthorityCode);
4464 :
4465 0 : rc = sqlite3_get_table(hDB, osCommand, &papszResult,
4466 : &nRowCount, &nColCount, &pszErrMsg);
4467 :
4468 0 : if (rc != SQLITE_OK)
4469 : {
4470 0 : sqlite3_free(pszErrMsg);
4471 : }
4472 : }
4473 : }
4474 :
4475 171 : if (rc == SQLITE_OK && nRowCount == 1)
4476 : {
4477 146 : nSRSId = (papszResult[1] != nullptr) ? atoi(papszResult[1])
4478 : : m_nUndefinedSRID;
4479 146 : sqlite3_free_table(papszResult);
4480 :
4481 146 : if (nSRSId != m_nUndefinedSRID)
4482 : {
4483 146 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
4484 146 : AddSRIDToCache(nSRSId, std::move(poSRS));
4485 : }
4486 :
4487 146 : return nSRSId;
4488 : }
4489 25 : sqlite3_free_table(papszResult);
4490 : }
4491 : }
4492 :
4493 : /* -------------------------------------------------------------------- */
4494 : /* Search for existing record using either WKT definition or */
4495 : /* PROJ.4 string (SpatiaLite variant). */
4496 : /* -------------------------------------------------------------------- */
4497 56 : CPLString osWKT;
4498 56 : CPLString osProj4;
4499 :
4500 : /* -------------------------------------------------------------------- */
4501 : /* Translate SRS to WKT. */
4502 : /* -------------------------------------------------------------------- */
4503 28 : char *pszWKT = nullptr;
4504 :
4505 28 : if (poSRS->exportToWkt(&pszWKT) != OGRERR_NONE)
4506 : {
4507 0 : CPLFree(pszWKT);
4508 0 : return m_nUndefinedSRID;
4509 : }
4510 :
4511 28 : osWKT = pszWKT;
4512 28 : CPLFree(pszWKT);
4513 28 : pszWKT = nullptr;
4514 :
4515 28 : const char *pszSRTEXTColName = GetSRTEXTColName();
4516 :
4517 28 : if (pszSRTEXTColName != nullptr)
4518 : {
4519 : /* --------------------------------------------------------------------
4520 : */
4521 : /* Try to find based on the WKT match. */
4522 : /* --------------------------------------------------------------------
4523 : */
4524 : osCommand.Printf("SELECT srid FROM spatial_ref_sys WHERE \"%s\" = ? "
4525 : "LIMIT 2",
4526 28 : SQLEscapeName(pszSRTEXTColName).c_str());
4527 : }
4528 :
4529 : /* -------------------------------------------------------------------- */
4530 : /* Handle SpatiaLite (< 4) flavor of the spatial_ref_sys. */
4531 : /* -------------------------------------------------------------------- */
4532 : else
4533 : {
4534 : /* --------------------------------------------------------------------
4535 : */
4536 : /* Translate SRS to PROJ.4 string. */
4537 : /* --------------------------------------------------------------------
4538 : */
4539 0 : char *pszProj4 = nullptr;
4540 :
4541 0 : if (poSRS->exportToProj4(&pszProj4) != OGRERR_NONE)
4542 : {
4543 0 : CPLFree(pszProj4);
4544 0 : return m_nUndefinedSRID;
4545 : }
4546 :
4547 0 : osProj4 = pszProj4;
4548 0 : CPLFree(pszProj4);
4549 0 : pszProj4 = nullptr;
4550 :
4551 : /* --------------------------------------------------------------------
4552 : */
4553 : /* Try to find based on the PROJ.4 match. */
4554 : /* --------------------------------------------------------------------
4555 : */
4556 : osCommand.Printf(
4557 0 : "SELECT srid FROM spatial_ref_sys WHERE proj4text = ? LIMIT 2");
4558 : }
4559 :
4560 28 : sqlite3_stmt *hSelectStmt = prepareSql(hDB, osCommand.c_str());
4561 :
4562 28 : int rc = SQLITE_OK;
4563 28 : if (hSelectStmt)
4564 56 : rc = sqlite3_bind_text(hSelectStmt, 1,
4565 28 : (pszSRTEXTColName != nullptr) ? osWKT.c_str()
4566 0 : : osProj4.c_str(),
4567 : -1, SQLITE_STATIC);
4568 : else
4569 0 : rc = SQLITE_ERROR;
4570 :
4571 28 : if (rc == SQLITE_OK)
4572 28 : rc = sqlite3_step(hSelectStmt);
4573 :
4574 28 : if (rc == SQLITE_ROW)
4575 : {
4576 0 : if (sqlite3_column_type(hSelectStmt, 0) == SQLITE_INTEGER)
4577 0 : nSRSId = sqlite3_column_int(hSelectStmt, 0);
4578 : else
4579 0 : nSRSId = m_nUndefinedSRID;
4580 :
4581 0 : sqlite3_finalize(hSelectStmt);
4582 :
4583 0 : if (nSRSId != m_nUndefinedSRID)
4584 : {
4585 0 : AddSRIDToCache(nSRSId, std::move(poSRS));
4586 : }
4587 :
4588 0 : return nSRSId;
4589 : }
4590 :
4591 : /* -------------------------------------------------------------------- */
4592 : /* If the command actually failed, then the metadata table is */
4593 : /* likely missing, so we give up. */
4594 : /* -------------------------------------------------------------------- */
4595 28 : if (rc != SQLITE_DONE && rc != SQLITE_ROW)
4596 : {
4597 0 : sqlite3_finalize(hSelectStmt);
4598 0 : return m_nUndefinedSRID;
4599 : }
4600 :
4601 28 : sqlite3_finalize(hSelectStmt);
4602 :
4603 : /* -------------------------------------------------------------------- */
4604 : /* Translate SRS to PROJ.4 string (if not already done) */
4605 : /* -------------------------------------------------------------------- */
4606 28 : if (osProj4.empty())
4607 : {
4608 28 : char *pszProj4 = nullptr;
4609 28 : if (poSRS->exportToProj4(&pszProj4) == OGRERR_NONE)
4610 : {
4611 26 : osProj4 = pszProj4;
4612 : }
4613 28 : CPLFree(pszProj4);
4614 28 : pszProj4 = nullptr;
4615 : }
4616 :
4617 : /* -------------------------------------------------------------------- */
4618 : /* If we have an authority code try to assign SRS ID the same */
4619 : /* as that code. */
4620 : /* -------------------------------------------------------------------- */
4621 28 : if (pszAuthorityCode != nullptr && strlen(pszAuthorityCode) > 0)
4622 : {
4623 : osCommand.Printf("SELECT * FROM spatial_ref_sys WHERE auth_srid='%s' "
4624 : "LIMIT 2",
4625 25 : SQLEscapeLiteral(pszAuthorityCode).c_str());
4626 25 : rc = sqlite3_get_table(hDB, osCommand, &papszResult, &nRowCount,
4627 : &nColCount, &pszErrMsg);
4628 :
4629 25 : if (rc != SQLITE_OK)
4630 : {
4631 0 : CPLError(CE_Failure, CPLE_AppDefined,
4632 : "exec(SELECT '%s' FROM spatial_ref_sys) failed: %s",
4633 : pszAuthorityCode, pszErrMsg);
4634 0 : sqlite3_free(pszErrMsg);
4635 : }
4636 :
4637 : /* --------------------------------------------------------------------
4638 : */
4639 : /* If there is no SRS ID with such auth_srid, use it as SRS ID. */
4640 : /* --------------------------------------------------------------------
4641 : */
4642 25 : if (nRowCount < 1)
4643 : {
4644 25 : nSRSId = atoi(pszAuthorityCode);
4645 : /* The authority code might be non numeric, e.g. IGNF:LAMB93 */
4646 : /* in which case we might fallback to the fake OGR authority */
4647 : /* for spatialite, since its auth_srid is INTEGER */
4648 25 : if (nSRSId == 0)
4649 : {
4650 0 : nSRSId = m_nUndefinedSRID;
4651 0 : if (m_bIsSpatiaLiteDB)
4652 0 : pszAuthorityName = nullptr;
4653 : }
4654 : }
4655 25 : sqlite3_free_table(papszResult);
4656 : }
4657 :
4658 : /* -------------------------------------------------------------------- */
4659 : /* Otherwise get the current maximum srid in the srs table. */
4660 : /* -------------------------------------------------------------------- */
4661 28 : if (nSRSId == m_nUndefinedSRID)
4662 : {
4663 : rc =
4664 3 : sqlite3_get_table(hDB, "SELECT MAX(srid) FROM spatial_ref_sys",
4665 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
4666 :
4667 3 : if (rc != SQLITE_OK)
4668 : {
4669 0 : CPLError(CE_Failure, CPLE_AppDefined,
4670 : "SELECT of the maximum SRS ID failed: %s", pszErrMsg);
4671 0 : sqlite3_free(pszErrMsg);
4672 0 : return m_nUndefinedSRID;
4673 : }
4674 :
4675 3 : if (nRowCount < 1 || !papszResult[1])
4676 1 : nSRSId = 50000;
4677 : else
4678 2 : nSRSId = atoi(papszResult[1]) + 1; // Insert as the next SRS ID
4679 3 : sqlite3_free_table(papszResult);
4680 : }
4681 :
4682 : /* -------------------------------------------------------------------- */
4683 : /* Try adding the SRS to the SRS table. */
4684 : /* -------------------------------------------------------------------- */
4685 :
4686 28 : const char *apszToInsert[] = {nullptr, nullptr, nullptr,
4687 : nullptr, nullptr, nullptr};
4688 :
4689 28 : if (!m_bIsSpatiaLiteDB)
4690 : {
4691 25 : if (pszAuthorityName != nullptr)
4692 : {
4693 : osCommand.Printf(
4694 : "INSERT INTO spatial_ref_sys (srid,srtext,auth_name,auth_srid) "
4695 : " VALUES (%d, ?, ?, ?)",
4696 24 : nSRSId);
4697 24 : apszToInsert[0] = osWKT.c_str();
4698 24 : apszToInsert[1] = pszAuthorityName;
4699 24 : apszToInsert[2] = pszAuthorityCode;
4700 : }
4701 : else
4702 : {
4703 : osCommand.Printf("INSERT INTO spatial_ref_sys (srid,srtext) "
4704 : " VALUES (%d, ?)",
4705 1 : nSRSId);
4706 1 : apszToInsert[0] = osWKT.c_str();
4707 : }
4708 : }
4709 : else
4710 : {
4711 6 : CPLString osSRTEXTColNameWithCommaBefore;
4712 3 : if (pszSRTEXTColName != nullptr)
4713 3 : osSRTEXTColNameWithCommaBefore.Printf(", %s", pszSRTEXTColName);
4714 :
4715 3 : const char *pszProjCS = poSRS->GetAttrValue("PROJCS");
4716 3 : if (pszProjCS == nullptr)
4717 1 : pszProjCS = poSRS->GetAttrValue("GEOGCS");
4718 :
4719 3 : if (pszAuthorityName != nullptr)
4720 : {
4721 1 : if (pszProjCS)
4722 : {
4723 : osCommand.Printf(
4724 : "INSERT INTO spatial_ref_sys "
4725 : "(srid, auth_name, auth_srid, ref_sys_name, proj4text%s) "
4726 : "VALUES (%d, ?, ?, ?, ?%s)",
4727 : (pszSRTEXTColName != nullptr)
4728 1 : ? osSRTEXTColNameWithCommaBefore.c_str()
4729 : : "",
4730 2 : nSRSId, (pszSRTEXTColName != nullptr) ? ", ?" : "");
4731 1 : apszToInsert[0] = pszAuthorityName;
4732 1 : apszToInsert[1] = pszAuthorityCode;
4733 1 : apszToInsert[2] = pszProjCS;
4734 1 : apszToInsert[3] = osProj4.c_str();
4735 1 : apszToInsert[4] =
4736 1 : (pszSRTEXTColName != nullptr) ? osWKT.c_str() : nullptr;
4737 : }
4738 : else
4739 : {
4740 : osCommand.Printf("INSERT INTO spatial_ref_sys "
4741 : "(srid, auth_name, auth_srid, proj4text%s) "
4742 : "VALUES (%d, ?, ?, ?%s)",
4743 : (pszSRTEXTColName != nullptr)
4744 0 : ? osSRTEXTColNameWithCommaBefore.c_str()
4745 : : "",
4746 : nSRSId,
4747 0 : (pszSRTEXTColName != nullptr) ? ", ?" : "");
4748 0 : apszToInsert[0] = pszAuthorityName;
4749 0 : apszToInsert[1] = pszAuthorityCode;
4750 0 : apszToInsert[2] = osProj4.c_str();
4751 0 : apszToInsert[3] =
4752 0 : (pszSRTEXTColName != nullptr) ? osWKT.c_str() : nullptr;
4753 : }
4754 : }
4755 : else
4756 : {
4757 : /* SpatiaLite spatial_ref_sys auth_name and auth_srid columns must
4758 : * be NOT NULL */
4759 : /* so insert within a fake OGR "authority" */
4760 2 : if (pszProjCS)
4761 : {
4762 : osCommand.Printf("INSERT INTO spatial_ref_sys "
4763 : "(srid, auth_name, auth_srid, ref_sys_name, "
4764 : "proj4text%s) VALUES (%d, 'OGR', %d, ?, ?%s)",
4765 : (pszSRTEXTColName != nullptr)
4766 1 : ? osSRTEXTColNameWithCommaBefore.c_str()
4767 : : "",
4768 : nSRSId, nSRSId,
4769 2 : (pszSRTEXTColName != nullptr) ? ", ?" : "");
4770 1 : apszToInsert[0] = pszProjCS;
4771 1 : apszToInsert[1] = osProj4.c_str();
4772 1 : apszToInsert[2] =
4773 1 : (pszSRTEXTColName != nullptr) ? osWKT.c_str() : nullptr;
4774 : }
4775 : else
4776 : {
4777 : osCommand.Printf("INSERT INTO spatial_ref_sys "
4778 : "(srid, auth_name, auth_srid, proj4text%s) "
4779 : "VALUES (%d, 'OGR', %d, ?%s)",
4780 : (pszSRTEXTColName != nullptr)
4781 1 : ? osSRTEXTColNameWithCommaBefore.c_str()
4782 : : "",
4783 : nSRSId, nSRSId,
4784 2 : (pszSRTEXTColName != nullptr) ? ", ?" : "");
4785 1 : apszToInsert[0] = osProj4.c_str();
4786 1 : apszToInsert[1] =
4787 1 : (pszSRTEXTColName != nullptr) ? osWKT.c_str() : nullptr;
4788 : }
4789 : }
4790 : }
4791 :
4792 28 : sqlite3_stmt *hInsertStmt = prepareSql(hDB, osCommand.c_str());
4793 28 : if (!hInsertStmt)
4794 0 : rc = SQLITE_ERROR;
4795 :
4796 111 : for (int i = 0; rc == SQLITE_OK && apszToInsert[i] != nullptr; i++)
4797 : {
4798 83 : rc = sqlite3_bind_text(hInsertStmt, i + 1, apszToInsert[i], -1,
4799 : SQLITE_STATIC);
4800 : }
4801 :
4802 28 : if (rc == SQLITE_OK)
4803 28 : rc = sqlite3_step(hInsertStmt);
4804 :
4805 28 : if (rc != SQLITE_OK && rc != SQLITE_DONE)
4806 : {
4807 0 : CPLError(CE_Failure, CPLE_AppDefined, "Unable to insert SRID (%s): %s",
4808 : osCommand.c_str(), sqlite3_errmsg(hDB));
4809 :
4810 0 : sqlite3_finalize(hInsertStmt);
4811 0 : return FALSE;
4812 : }
4813 :
4814 28 : sqlite3_finalize(hInsertStmt);
4815 :
4816 28 : if (nSRSId != m_nUndefinedSRID)
4817 : {
4818 28 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
4819 28 : AddSRIDToCache(nSRSId, std::move(poSRS));
4820 : }
4821 :
4822 28 : return nSRSId;
4823 : }
4824 :
4825 : /************************************************************************/
4826 : /* FetchSRS() */
4827 : /* */
4828 : /* Return a SRS corresponding to a particular id. Note that */
4829 : /* reference counting should be honoured on the returned */
4830 : /* OGRSpatialReference, as handles may be cached. */
4831 : /************************************************************************/
4832 :
4833 582 : OGRSpatialReference *OGRSQLiteDataSource::FetchSRS(int nId)
4834 :
4835 : {
4836 582 : if (nId <= 0)
4837 365 : return nullptr;
4838 :
4839 : /* -------------------------------------------------------------------- */
4840 : /* First, we look through our SRID cache, is it there? */
4841 : /* -------------------------------------------------------------------- */
4842 217 : const auto oIter = m_oSRSCache.find(nId);
4843 217 : if (oIter != m_oSRSCache.end())
4844 : {
4845 150 : return oIter->second.get();
4846 : }
4847 :
4848 : /* -------------------------------------------------------------------- */
4849 : /* Try looking up in spatial_ref_sys table. */
4850 : /* -------------------------------------------------------------------- */
4851 67 : char *pszErrMsg = nullptr;
4852 67 : char **papszResult = nullptr;
4853 67 : int nRowCount = 0;
4854 67 : int nColCount = 0;
4855 134 : OGRSpatialReferenceRefCountedPtr poSRS;
4856 :
4857 134 : CPLString osCommand;
4858 67 : osCommand.Printf("SELECT srtext FROM spatial_ref_sys WHERE srid = %d "
4859 : "LIMIT 2",
4860 67 : nId);
4861 67 : int rc = sqlite3_get_table(hDB, osCommand, &papszResult, &nRowCount,
4862 : &nColCount, &pszErrMsg);
4863 :
4864 67 : if (rc == SQLITE_OK)
4865 : {
4866 59 : if (nRowCount < 1)
4867 : {
4868 2 : sqlite3_free_table(papszResult);
4869 2 : return nullptr;
4870 : }
4871 :
4872 57 : char **papszRow = papszResult + nColCount;
4873 57 : if (papszRow[0] != nullptr)
4874 : {
4875 114 : CPLString osWKT = papszRow[0];
4876 :
4877 : /* --------------------------------------------------------------------
4878 : */
4879 : /* Translate into a spatial reference. */
4880 : /* --------------------------------------------------------------------
4881 : */
4882 57 : poSRS = OGRSpatialReferenceRefCountedPtr::makeInstance();
4883 57 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
4884 57 : if (poSRS->importFromWkt(osWKT.c_str()) != OGRERR_NONE)
4885 : {
4886 0 : poSRS.reset();
4887 : }
4888 : }
4889 :
4890 57 : sqlite3_free_table(papszResult);
4891 : }
4892 :
4893 : /* -------------------------------------------------------------------- */
4894 : /* Next try SpatiaLite flavor. SpatiaLite uses PROJ.4 strings */
4895 : /* in 'proj4text' column instead of WKT in 'srtext'. Note: recent */
4896 : /* versions of spatialite have a srs_wkt column too */
4897 : /* -------------------------------------------------------------------- */
4898 : else
4899 : {
4900 8 : sqlite3_free(pszErrMsg);
4901 8 : pszErrMsg = nullptr;
4902 :
4903 8 : const char *pszSRTEXTColName = GetSRTEXTColName();
4904 8 : CPLString osSRTEXTColNameWithCommaBefore;
4905 8 : if (pszSRTEXTColName != nullptr)
4906 8 : osSRTEXTColNameWithCommaBefore.Printf(", %s", pszSRTEXTColName);
4907 :
4908 8 : osCommand.Printf(
4909 : "SELECT proj4text, auth_name, auth_srid%s FROM spatial_ref_sys "
4910 : "WHERE srid = %d LIMIT 2",
4911 : (pszSRTEXTColName != nullptr)
4912 8 : ? osSRTEXTColNameWithCommaBefore.c_str()
4913 : : "",
4914 16 : nId);
4915 8 : rc = sqlite3_get_table(hDB, osCommand, &papszResult, &nRowCount,
4916 : &nColCount, &pszErrMsg);
4917 8 : if (rc == SQLITE_OK)
4918 : {
4919 8 : if (nRowCount < 1)
4920 : {
4921 7 : sqlite3_free_table(papszResult);
4922 7 : return nullptr;
4923 : }
4924 :
4925 : /* --------------------------------------------------------------------
4926 : */
4927 : /* Translate into a spatial reference. */
4928 : /* --------------------------------------------------------------------
4929 : */
4930 1 : char **papszRow = papszResult + nColCount;
4931 :
4932 1 : const char *pszProj4Text = papszRow[0];
4933 1 : const char *pszAuthName = papszRow[1];
4934 1 : int nAuthSRID = (papszRow[2] != nullptr) ? atoi(papszRow[2]) : 0;
4935 1 : const char *pszWKT =
4936 1 : (pszSRTEXTColName != nullptr) ? papszRow[3] : nullptr;
4937 :
4938 1 : poSRS = OGRSpatialReferenceRefCountedPtr::makeInstance();
4939 1 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
4940 :
4941 : /* Try first from EPSG code */
4942 2 : if (pszAuthName != nullptr && EQUAL(pszAuthName, "EPSG") &&
4943 1 : poSRS->importFromEPSG(nAuthSRID) == OGRERR_NONE)
4944 : {
4945 : /* Do nothing */
4946 : }
4947 : /* Then from WKT string */
4948 0 : else if (pszWKT != nullptr &&
4949 0 : poSRS->importFromWkt(pszWKT) == OGRERR_NONE)
4950 : {
4951 : /* Do nothing */
4952 : }
4953 : /* Finally from Proj4 string */
4954 0 : else if (pszProj4Text != nullptr &&
4955 0 : poSRS->importFromProj4(pszProj4Text) == OGRERR_NONE)
4956 : {
4957 : /* Do nothing */
4958 : }
4959 : else
4960 : {
4961 0 : poSRS.reset();
4962 : }
4963 :
4964 1 : sqlite3_free_table(papszResult);
4965 : }
4966 :
4967 : /* --------------------------------------------------------------------
4968 : */
4969 : /* No success, report an error. */
4970 : /* --------------------------------------------------------------------
4971 : */
4972 : else
4973 : {
4974 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s: %s", osCommand.c_str(),
4975 : pszErrMsg);
4976 0 : sqlite3_free(pszErrMsg);
4977 0 : return nullptr;
4978 : }
4979 : }
4980 :
4981 58 : if (poSRS)
4982 58 : poSRS->StripTOWGS84IfKnownDatumAndAllowed();
4983 :
4984 : /* -------------------------------------------------------------------- */
4985 : /* Add to the cache. */
4986 : /* -------------------------------------------------------------------- */
4987 58 : return AddSRIDToCache(nId, std::move(poSRS));
4988 : }
4989 :
4990 : /************************************************************************/
4991 : /* SetName() */
4992 : /************************************************************************/
4993 :
4994 0 : void OGRSQLiteDataSource::SetName(const char *pszNameIn)
4995 : {
4996 0 : CPLFree(m_pszFilename);
4997 0 : m_pszFilename = CPLStrdup(pszNameIn);
4998 0 : }
4999 :
5000 : /************************************************************************/
5001 : /* GetEnvelopeFromSQL() */
5002 : /************************************************************************/
5003 :
5004 : const OGREnvelope *
5005 16 : OGRSQLiteBaseDataSource::GetEnvelopeFromSQL(const CPLString &osSQL)
5006 : {
5007 16 : const auto oIter = oMapSQLEnvelope.find(osSQL);
5008 16 : if (oIter != oMapSQLEnvelope.end())
5009 5 : return &oIter->second;
5010 : else
5011 11 : return nullptr;
5012 : }
5013 :
5014 : /************************************************************************/
5015 : /* SetEnvelopeForSQL() */
5016 : /************************************************************************/
5017 :
5018 5 : void OGRSQLiteBaseDataSource::SetEnvelopeForSQL(const CPLString &osSQL,
5019 : const OGREnvelope &oEnvelope)
5020 : {
5021 5 : oMapSQLEnvelope[osSQL] = oEnvelope;
5022 5 : }
5023 :
5024 : /************************************************************************/
5025 : /* SetQueryLoggerFunc() */
5026 : /************************************************************************/
5027 :
5028 1 : bool OGRSQLiteBaseDataSource::SetQueryLoggerFunc(
5029 : GDALQueryLoggerFunc pfnQueryLoggerFuncIn, void *poQueryLoggerArgIn)
5030 : {
5031 1 : pfnQueryLoggerFunc = pfnQueryLoggerFuncIn;
5032 1 : poQueryLoggerArg = poQueryLoggerArgIn;
5033 :
5034 1 : if (pfnQueryLoggerFunc)
5035 : {
5036 1 : sqlite3_trace_v2(
5037 : hDB, SQLITE_TRACE_PROFILE,
5038 17 : [](unsigned int /* traceProfile */, void *context,
5039 : void *preparedStatement, void *executionTime) -> int
5040 : {
5041 17 : if (context)
5042 : {
5043 17 : char *pzsSql{sqlite3_expanded_sql(
5044 : reinterpret_cast<sqlite3_stmt *>(preparedStatement))};
5045 17 : if (pzsSql)
5046 : {
5047 34 : const std::string sql{pzsSql};
5048 17 : sqlite3_free(pzsSql);
5049 17 : const uint64_t executionTimeMilliSeconds{
5050 : static_cast<uint64_t>(
5051 17 : *reinterpret_cast<uint64_t *>(executionTime) /
5052 : 1e+6)};
5053 17 : OGRSQLiteBaseDataSource *source{
5054 : reinterpret_cast<OGRSQLiteBaseDataSource *>(
5055 : context)};
5056 17 : if (source->pfnQueryLoggerFunc)
5057 : {
5058 17 : source->pfnQueryLoggerFunc(
5059 : sql.c_str(), nullptr, -1,
5060 : executionTimeMilliSeconds,
5061 : source->poQueryLoggerArg);
5062 : }
5063 : }
5064 : }
5065 17 : return 0;
5066 : },
5067 : reinterpret_cast<void *>(this));
5068 1 : return true;
5069 : }
5070 0 : return false;
5071 : }
5072 :
5073 : /************************************************************************/
5074 : /* AbortSQL() */
5075 : /************************************************************************/
5076 :
5077 2 : OGRErr OGRSQLiteBaseDataSource::AbortSQL()
5078 : {
5079 2 : sqlite3_interrupt(hDB);
5080 2 : return OGRERR_NONE;
5081 : }
|