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