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