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