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