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