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