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 3777 : bool OGRSQLiteBaseDataSource::InitSpatialite()
162 : {
163 7025 : if (hSpatialiteCtxt == nullptr &&
164 3248 : CPLTestBool(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")))
165 : {
166 : #ifdef SPATIALITE_DLOPEN
167 : if (!OGRSQLiteLoadSpatialiteSymbols())
168 : return false;
169 : #endif
170 3248 : CPLAssert(hSpatialiteCtxt == nullptr);
171 3248 : hSpatialiteCtxt = pfn_spatialite_alloc_connection();
172 3248 : if (hSpatialiteCtxt != nullptr)
173 : {
174 6496 : pfn_spatialite_init_ex(hDB, hSpatialiteCtxt,
175 3248 : CPLTestBool(CPLGetConfigOption(
176 : "SPATIALITE_INIT_VERBOSE", "FALSE")));
177 : }
178 : }
179 3777 : return hSpatialiteCtxt != nullptr;
180 : }
181 :
182 : /************************************************************************/
183 : /* FinishSpatialite() */
184 : /************************************************************************/
185 :
186 3726 : void OGRSQLiteBaseDataSource::FinishSpatialite()
187 : {
188 3726 : if (hSpatialiteCtxt != nullptr)
189 : {
190 3247 : 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 6494 : std::lock_guard oLock(oCleanupMutex);
197 3247 : pfn_spatialite_cleanup_ex(ctxt);
198 : }
199 : // coverity[thread1_overwrites_value_in_field]
200 3247 : hSpatialiteCtxt = nullptr;
201 : }
202 3726 : }
203 :
204 : /************************************************************************/
205 : /* IsSpatialiteLoaded() */
206 : /************************************************************************/
207 :
208 12917 : bool OGRSQLiteBaseDataSource::IsSpatialiteLoaded()
209 : {
210 12917 : 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 943 : void OGRSQLiteDriverUnload(GDALDriver *)
236 : {
237 : #ifdef HAVE_SPATIALITE
238 943 : if (pfn_spatialite_shutdown != nullptr)
239 943 : pfn_spatialite_shutdown();
240 : #ifdef SPATIALITE_DLOPEN
241 : if (hMutexLoadSpatialiteSymbols != nullptr)
242 : {
243 : CPLDestroyMutex(hMutexLoadSpatialiteSymbols);
244 : hMutexLoadSpatialiteSymbols = nullptr;
245 : }
246 : #endif
247 : #endif
248 943 : }
249 :
250 : /************************************************************************/
251 : /* DealWithOgrSchemaOpenOption() */
252 : /************************************************************************/
253 1745 : bool OGRSQLiteBaseDataSource::DealWithOgrSchemaOpenOption(
254 : CSLConstList papszOpenOptionsIn)
255 : {
256 : std::string osFieldsSchemaOverrideParam =
257 3490 : CSLFetchNameValueDef(papszOpenOptionsIn, "OGR_SCHEMA", "");
258 :
259 1745 : 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 1741 : return true;
363 : }
364 :
365 : /************************************************************************/
366 : /* GetSpatialiteVersionNumber() */
367 : /************************************************************************/
368 :
369 6207 : int OGRSQLiteBaseDataSource::GetSpatialiteVersionNumber()
370 : {
371 6207 : int v = 0;
372 : #ifdef HAVE_SPATIALITE
373 6207 : if (IsSpatialiteLoaded())
374 : {
375 : const CPLStringList aosTokens(
376 12298 : CSLTokenizeString2(pfn_spatialite_version(), ".", 0));
377 6149 : if (aosTokens.size() >= 2)
378 : {
379 6149 : v = MakeSpatialiteVersionNumber(
380 : atoi(aosTokens[0]), atoi(aosTokens[1]),
381 6149 : aosTokens.size() == 3 ? atoi(aosTokens[2]) : 0);
382 : }
383 : }
384 : #endif
385 6207 : 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 3715 : OGRSQLiteBaseDataSource::~OGRSQLiteBaseDataSource()
609 :
610 : {
611 3715 : CloseDB();
612 :
613 3715 : FinishSpatialite();
614 :
615 3715 : if (m_bCallUndeclareFileNotToOpen)
616 : {
617 1785 : GDALOpenInfoUnDeclareFileNotToOpen(m_pszFilename);
618 : }
619 :
620 3715 : 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 3715 : CPLFree(m_pszFilename);
642 3715 : }
643 :
644 : /************************************************************************/
645 : /* CloseDB() */
646 : /************************************************************************/
647 :
648 7442 : bool OGRSQLiteBaseDataSource::CloseDB()
649 : {
650 7442 : bool bOK = true;
651 7442 : if (hDB != nullptr)
652 : {
653 3361 : bOK = (sqlite3_close(hDB) == SQLITE_OK);
654 3361 : 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 7940 : if (eAccess == GA_ReadOnly &&
661 1218 : !(STARTS_WITH(m_pszFilename, "/vsicurl/") ||
662 1214 : STARTS_WITH(m_pszFilename, "/vsitar/") ||
663 5789 : STARTS_WITH(m_pszFilename, "/vsizip/")) &&
664 1210 : 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 7442 : if (pMyVFS)
716 : {
717 2653 : sqlite3_vfs_unregister(pMyVFS);
718 2653 : CPLFree(pMyVFS->pAppData);
719 2653 : CPLFree(pMyVFS);
720 2653 : pMyVFS = nullptr;
721 : }
722 :
723 7442 : return bOK;
724 : }
725 :
726 : /* Returns the first row of first column of SQL as integer */
727 72 : OGRErr OGRSQLiteBaseDataSource::PragmaCheck(const char *pszPragma,
728 : const char *pszExpected,
729 : int nRowsExpected)
730 : {
731 72 : CPLAssert(pszPragma != nullptr);
732 72 : CPLAssert(pszExpected != nullptr);
733 72 : CPLAssert(nRowsExpected >= 0);
734 :
735 72 : char **papszResult = nullptr;
736 72 : int nRowCount = 0;
737 72 : int nColCount = 0;
738 72 : char *pszErrMsg = nullptr;
739 :
740 : int rc =
741 72 : sqlite3_get_table(hDB, CPLSPrintf("PRAGMA %s", pszPragma), &papszResult,
742 : &nRowCount, &nColCount, &pszErrMsg);
743 :
744 72 : 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 72 : 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 72 : 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 72 : sqlite3_free_table(papszResult);
771 :
772 72 : 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 12339 : int OGRSQLiteBaseDataSource::prepareSql(sqlite3 *db, const char *zSql,
957 : int nByte, sqlite3_stmt **ppStmt,
958 : const char **pzTail)
959 : {
960 12339 : const int rc{sqlite3_prepare_v2(db, zSql, nByte, ppStmt, pzTail)};
961 12339 : 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 12339 : return rc;
968 : }
969 :
970 : /************************************************************************/
971 : /* OGRSQLiteDataSource() */
972 : /************************************************************************/
973 :
974 1368 : OGRSQLiteDataSource::OGRSQLiteDataSource()
975 : {
976 1368 : m_adfGeoTransform[0] = 0.0;
977 1368 : m_adfGeoTransform[1] = 1.0;
978 1368 : m_adfGeoTransform[2] = 0.0;
979 1368 : m_adfGeoTransform[3] = 0.0;
980 1368 : m_adfGeoTransform[4] = 0.0;
981 1368 : m_adfGeoTransform[5] = 1.0;
982 1368 : }
983 :
984 : /************************************************************************/
985 : /* ~OGRSQLiteDataSource() */
986 : /************************************************************************/
987 :
988 2734 : OGRSQLiteDataSource::~OGRSQLiteDataSource()
989 :
990 : {
991 1367 : OGRSQLiteDataSource::Close();
992 2734 : }
993 :
994 : /************************************************************************/
995 : /* Close() */
996 : /************************************************************************/
997 :
998 1993 : CPLErr OGRSQLiteDataSource::Close()
999 : {
1000 1993 : CPLErr eErr = CE_None;
1001 1993 : if (nOpenFlags != OPEN_FLAGS_CLOSED)
1002 : {
1003 1367 : 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 1367 : for (size_t i = 0; i < m_apoOverviewDS.size(); ++i)
1013 : {
1014 0 : delete m_apoOverviewDS[i];
1015 : }
1016 :
1017 1367 : if (!m_apoLayers.empty() || !m_apoInvisibleLayers.empty())
1018 : {
1019 : // Close any remaining iterator
1020 2703 : for (auto &poLayer : m_apoLayers)
1021 1849 : poLayer->ResetReading();
1022 856 : for (auto &poLayer : m_apoInvisibleLayers)
1023 2 : poLayer->ResetReading();
1024 :
1025 : // Create spatial indices in a transaction for faster execution
1026 854 : if (hDB)
1027 854 : SoftStartTransaction();
1028 2703 : for (auto &poLayer : m_apoLayers)
1029 : {
1030 1849 : if (poLayer->IsTableLayer())
1031 : {
1032 : OGRSQLiteTableLayer *poTableLayer =
1033 1844 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
1034 1844 : poTableLayer->RunDeferredCreationIfNecessary();
1035 1844 : poTableLayer->CreateSpatialIndexIfNecessary();
1036 : }
1037 : }
1038 854 : if (hDB)
1039 854 : SoftCommitTransaction();
1040 : }
1041 :
1042 1367 : SaveStatistics();
1043 :
1044 1367 : m_apoLayers.clear();
1045 1367 : m_apoInvisibleLayers.clear();
1046 :
1047 1367 : m_oSRSCache.clear();
1048 :
1049 1367 : if (!CloseDB())
1050 0 : eErr = CE_Failure;
1051 : #ifdef HAVE_RASTERLITE2
1052 : FinishRasterLite2();
1053 : #endif
1054 :
1055 1367 : if (GDALPamDataset::Close() != CE_None)
1056 0 : eErr = CE_Failure;
1057 : }
1058 1993 : 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 1367 : void OGRSQLiteDataSource::SaveStatistics()
1098 : {
1099 703 : if (!m_bIsSpatiaLiteDB || !IsSpatialiteLoaded() ||
1100 2070 : m_bLastSQLCommandIsUpdateLayerStatistics || !GetUpdate())
1101 745 : return;
1102 :
1103 622 : int nSavedAllLayersCacheData = -1;
1104 :
1105 1033 : for (auto &poLayer : m_apoLayers)
1106 : {
1107 411 : if (poLayer->IsTableLayer())
1108 : {
1109 : OGRSQLiteTableLayer *poTableLayer =
1110 410 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
1111 410 : int nSaveRet = poTableLayer->SaveStatistics();
1112 410 : if (nSaveRet >= 0)
1113 : {
1114 153 : if (nSavedAllLayersCacheData < 0)
1115 58 : nSavedAllLayersCacheData = nSaveRet;
1116 : else
1117 95 : nSavedAllLayersCacheData &= nSaveRet;
1118 : }
1119 : }
1120 : }
1121 :
1122 622 : 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 3350 : bool OGRSQLiteBaseDataSource::SetSynchronous()
1178 : {
1179 : const char *pszSqliteSync =
1180 3350 : CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", nullptr);
1181 3350 : if (pszSqliteSync != nullptr)
1182 : {
1183 1590 : const char *pszSQL = nullptr;
1184 1590 : if (EQUAL(pszSqliteSync, "OFF") || EQUAL(pszSqliteSync, "0") ||
1185 0 : EQUAL(pszSqliteSync, "FALSE"))
1186 1590 : 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 1590 : return pszSQL != nullptr && SQLCommand(hDB, pszSQL) == OGRERR_NONE;
1198 : }
1199 1760 : return true;
1200 : }
1201 :
1202 : /************************************************************************/
1203 : /* LoadExtensions() */
1204 : /************************************************************************/
1205 :
1206 3350 : void OGRSQLiteBaseDataSource::LoadExtensions()
1207 : {
1208 : const char *pszExtensions =
1209 3350 : CPLGetConfigOption("OGR_SQLITE_LOAD_EXTENSIONS", nullptr);
1210 3350 : 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 3350 : bool OGRSQLiteBaseDataSource::SetCacheSize()
1292 : {
1293 : const char *pszSqliteCacheMB =
1294 3350 : CPLGetConfigOption("OGR_SQLITE_CACHE", nullptr);
1295 3350 : 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 3350 : return true;
1314 : }
1315 :
1316 : /************************************************************************/
1317 : /* OGRSQLiteBaseDataSourceNotifyFileOpened() */
1318 : /************************************************************************/
1319 :
1320 21802 : static void OGRSQLiteBaseDataSourceNotifyFileOpened(void *pfnUserData,
1321 : const char *pszFilename,
1322 : VSILFILE *fp)
1323 : {
1324 : static_cast<OGRSQLiteBaseDataSource *>(pfnUserData)
1325 21802 : ->NotifyFileOpened(pszFilename, fp);
1326 21802 : }
1327 :
1328 : /************************************************************************/
1329 : /* NotifyFileOpened() */
1330 : /************************************************************************/
1331 :
1332 21802 : void OGRSQLiteBaseDataSource::NotifyFileOpened(const char *pszFilename,
1333 : VSILFILE *fp)
1334 : {
1335 21802 : if (strcmp(pszFilename, m_pszFilename) == 0)
1336 : {
1337 2654 : fpMainFile = fp;
1338 : }
1339 21802 : }
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 3364 : 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 3364 : if (bRegisterOGR2SQLiteExtensions)
1420 1365 : OGR2SQLITE_Register();
1421 :
1422 : const bool bUseOGRVFS =
1423 3364 : CPLTestBool(CPLGetConfigOption("SQLITE_USE_OGR_VFS", "NO")) ||
1424 4074 : 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 3364 : CPLTestBool(CSLFetchNameValueDef(papszOpenOptions, "NOLOCK", "NO"));
1431 3364 : const char *pszImmutable = CSLFetchNameValue(papszOpenOptions, "IMMUTABLE");
1432 3364 : const bool bImmutable = pszImmutable && CPLTestBool(pszImmutable);
1433 3364 : if (m_osFilenameForSQLiteOpen.empty() &&
1434 3353 : (flagsIn & SQLITE_OPEN_READWRITE) == 0 &&
1435 6717 : !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 3364 : if (m_osFilenameForSQLiteOpen.empty())
1472 : {
1473 3346 : m_osFilenameForSQLiteOpen = m_pszFilename;
1474 : }
1475 :
1476 : // No mutex since OGR objects are not supposed to be used concurrently
1477 : // from multiple threads.
1478 3364 : 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 3372 : 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 3364 : bool bPageSizeFound = false;
1491 3364 : bool bSecureDeleteFound = false;
1492 :
1493 : const char *pszSqlitePragma =
1494 3364 : CPLGetConfigOption("OGR_SQLITE_PRAGMA", nullptr);
1495 6728 : CPLString osJournalMode = CPLGetConfigOption("OGR_SQLITE_JOURNAL", "");
1496 :
1497 3364 : if (bUseOGRVFS)
1498 : {
1499 2654 : pMyVFS =
1500 2654 : OGRSQLiteCreateVFS(OGRSQLiteBaseDataSourceNotifyFileOpened, this);
1501 2654 : sqlite3_vfs_register(pMyVFS, 0);
1502 : }
1503 :
1504 3365 : for (int iterOpen = 0; iterOpen < 2; iterOpen++)
1505 : {
1506 3365 : CPLAssert(hDB == nullptr);
1507 3365 : int rc = sqlite3_open_v2(m_osFilenameForSQLiteOpen.c_str(), &hDB, flags,
1508 3365 : pMyVFS ? pMyVFS->zName : nullptr);
1509 3365 : if (rc != SQLITE_OK || !hDB)
1510 : {
1511 10 : CPLError(CE_Failure, CPLE_OpenFailed, "sqlite3_open(%s) failed: %s",
1512 : m_pszFilename,
1513 10 : hDB ? sqlite3_errmsg(hDB) : "(unknown error)");
1514 10 : sqlite3_close(hDB);
1515 10 : hDB = nullptr;
1516 10 : 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 3355 : int bDefensiveOldValue = 0;
1525 3355 : if (sqlite3_db_config(hDB, SQLITE_DBCONFIG_DEFENSIVE, -1,
1526 6710 : &bDefensiveOldValue) == SQLITE_OK &&
1527 3355 : 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 3355 : int nPersistentWAL = -1;
1543 3355 : sqlite3_file_control(hDB, "main", SQLITE_FCNTL_PERSIST_WAL,
1544 : &nPersistentWAL);
1545 3355 : 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 3355 : if (pszSqlitePragma != nullptr)
1561 : {
1562 : char **papszTokens =
1563 6 : CSLTokenizeString2(pszSqlitePragma, ",", CSLT_HONOURSTRINGS);
1564 12 : for (int i = 0; papszTokens[i] != nullptr; i++)
1565 : {
1566 6 : if (STARTS_WITH_CI(papszTokens[i], "PAGE_SIZE"))
1567 0 : bPageSizeFound = true;
1568 6 : else if (STARTS_WITH_CI(papszTokens[i], "JOURNAL_MODE"))
1569 : {
1570 0 : const char *pszEqual = strchr(papszTokens[i], '=');
1571 0 : if (pszEqual)
1572 : {
1573 0 : osJournalMode = pszEqual + 1;
1574 0 : osJournalMode.Trim();
1575 : // Only apply journal_mode after changing page_size
1576 0 : continue;
1577 : }
1578 : }
1579 6 : else if (STARTS_WITH_CI(papszTokens[i], "SECURE_DELETE"))
1580 1 : bSecureDeleteFound = true;
1581 :
1582 6 : const char *pszSQL = CPLSPrintf("PRAGMA %s", papszTokens[i]);
1583 :
1584 6 : CPL_IGNORE_RET_VAL(
1585 6 : sqlite3_exec(hDB, pszSQL, nullptr, nullptr, nullptr));
1586 : }
1587 6 : CSLDestroy(papszTokens);
1588 : }
1589 :
1590 3355 : const char *pszVal = CPLGetConfigOption("SQLITE_BUSY_TIMEOUT", "5000");
1591 3355 : if (pszVal != nullptr)
1592 : {
1593 3355 : sqlite3_busy_timeout(hDB, atoi(pszVal));
1594 : }
1595 :
1596 : #ifdef SQLITE_OPEN_URI
1597 3355 : if (iterOpen == 0 && bNoLock && !bImmutable)
1598 : {
1599 6 : int nRowCount = 0, nColCount = 0;
1600 6 : char **papszResult = nullptr;
1601 6 : rc = sqlite3_get_table(hDB, "PRAGMA journal_mode", &papszResult,
1602 : &nRowCount, &nColCount, nullptr);
1603 6 : bool bWal = false;
1604 : // rc == SQLITE_CANTOPEN seems to be what we get when issuing the
1605 : // above in nolock mode on a wal enabled file
1606 6 : if (rc != SQLITE_OK ||
1607 5 : (nRowCount == 1 && nColCount == 1 && papszResult[1] &&
1608 5 : EQUAL(papszResult[1], "wal")))
1609 : {
1610 1 : bWal = true;
1611 : }
1612 6 : sqlite3_free_table(papszResult);
1613 6 : if (bWal)
1614 : {
1615 1 : flags &= ~SQLITE_OPEN_URI;
1616 1 : sqlite3_close(hDB);
1617 1 : hDB = nullptr;
1618 1 : CPLDebug("SQLite",
1619 : "Cannot open %s in nolock mode because it is "
1620 : "presumably in -wal mode",
1621 : m_pszFilename);
1622 1 : m_osFilenameForSQLiteOpen = m_pszFilename;
1623 1 : continue;
1624 : }
1625 : }
1626 : #endif
1627 3354 : break;
1628 : }
1629 :
1630 3354 : if ((flagsIn & SQLITE_OPEN_CREATE) == 0)
1631 : {
1632 2160 : if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_READ", "NO")))
1633 : {
1634 1 : if (SQLGetInteger(hDB,
1635 : "SELECT 1 FROM sqlite_master "
1636 : "WHERE type = 'table' AND name = 'vfk_tables'",
1637 1 : nullptr))
1638 4 : return false; /* DB is valid VFK datasource */
1639 : }
1640 :
1641 2159 : int nRowCount = 0, nColCount = 0;
1642 2159 : char **papszResult = nullptr;
1643 2159 : char *pszErrMsg = nullptr;
1644 : int rc =
1645 2159 : sqlite3_get_table(hDB,
1646 : "SELECT 1 FROM sqlite_master "
1647 : "WHERE (type = 'trigger' OR type = 'view') AND ("
1648 : "sql LIKE '%%ogr_geocode%%' OR "
1649 : "sql LIKE '%%ogr_datasource_load_layers%%' OR "
1650 : "sql LIKE '%%ogr_GetConfigOption%%' OR "
1651 : "sql LIKE '%%ogr_SetConfigOption%%' ) "
1652 : "LIMIT 1",
1653 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
1654 2159 : if (rc != SQLITE_OK)
1655 : {
1656 3 : bool bIsWAL = false;
1657 3 : VSILFILE *fp = VSIFOpenL(m_pszFilename, "rb");
1658 3 : if (fp != nullptr)
1659 : {
1660 3 : GByte byVal = 0;
1661 3 : VSIFSeekL(fp, 18, SEEK_SET);
1662 3 : VSIFReadL(&byVal, 1, 1, fp);
1663 3 : bIsWAL = byVal == 2;
1664 3 : VSIFCloseL(fp);
1665 : }
1666 3 : if (bIsWAL)
1667 : {
1668 : #ifdef SQLITE_OPEN_URI
1669 5 : if (pszImmutable == nullptr &&
1670 4 : (flags & SQLITE_OPEN_READONLY) != 0 &&
1671 1 : m_osFilenameForSQLiteOpen == m_pszFilename)
1672 : {
1673 1 : CPLError(CE_Warning, CPLE_AppDefined,
1674 : "%s: this file is a WAL-enabled database. "
1675 : "It cannot be opened "
1676 : "because it is presumably read-only or in a "
1677 : "read-only directory. Retrying with IMMUTABLE=YES "
1678 : "open option",
1679 : pszErrMsg);
1680 1 : sqlite3_free(pszErrMsg);
1681 1 : CloseDB();
1682 1 : m_osFilenameForSQLiteOpen.clear();
1683 1 : papszOpenOptions =
1684 1 : CSLSetNameValue(papszOpenOptions, "IMMUTABLE", "YES");
1685 1 : return OpenOrCreateDB(flagsIn,
1686 : bRegisterOGR2SQLiteExtensions,
1687 1 : bLoadExtensions);
1688 : }
1689 : #endif
1690 :
1691 2 : CPLError(CE_Failure, CPLE_AppDefined,
1692 : "%s: this file is a WAL-enabled database. "
1693 : "It cannot be opened "
1694 : "because it is presumably read-only or in a "
1695 : "read-only directory.%s",
1696 : pszErrMsg,
1697 : #ifdef SQLITE_OPEN_URI
1698 : pszImmutable != nullptr
1699 : ? ""
1700 : : " Try opening with IMMUTABLE=YES open option"
1701 : #else
1702 : ""
1703 : #endif
1704 : );
1705 : }
1706 : else
1707 : {
1708 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrMsg);
1709 : }
1710 2 : sqlite3_free(pszErrMsg);
1711 2 : return false;
1712 : }
1713 :
1714 2156 : sqlite3_free_table(papszResult);
1715 :
1716 2156 : if (nRowCount > 0)
1717 : {
1718 0 : if (!CPLTestBool(CPLGetConfigOption(
1719 : "ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW", "NO")))
1720 : {
1721 0 : CPLError(CE_Failure, CPLE_OpenFailed, "%s",
1722 : "A trigger and/or view calls a OGR extension SQL "
1723 : "function that could be used to "
1724 : "steal data, or use network bandwidth, without your "
1725 : "consent.\n"
1726 : "The database will not be opened unless the "
1727 : "ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW "
1728 : "configuration option to YES.");
1729 0 : return false;
1730 : }
1731 : }
1732 : }
1733 :
1734 3358 : if (m_osFilenameForSQLiteOpen != m_pszFilename &&
1735 8 : (m_osFilenameForSQLiteOpen.find("?nolock=1") != std::string::npos ||
1736 2 : m_osFilenameForSQLiteOpen.find("&nolock=1") != std::string::npos))
1737 : {
1738 4 : m_bNoLock = true;
1739 4 : CPLDebug("SQLite", "%s open in nolock mode", m_pszFilename);
1740 : }
1741 :
1742 3350 : if (!bPageSizeFound && (flagsIn & SQLITE_OPEN_CREATE) != 0)
1743 : {
1744 : // Since sqlite 3.12 the default page_size is now 4096. But we
1745 : // can use that even with older versions.
1746 1194 : CPL_IGNORE_RET_VAL(sqlite3_exec(hDB, "PRAGMA page_size = 4096", nullptr,
1747 : nullptr, nullptr));
1748 : }
1749 :
1750 : // journal_mode = WAL must be done *AFTER* changing page size.
1751 3350 : if (!osJournalMode.empty())
1752 : {
1753 : const char *pszSQL =
1754 2 : CPLSPrintf("PRAGMA journal_mode = %s", osJournalMode.c_str());
1755 :
1756 2 : CPL_IGNORE_RET_VAL(
1757 2 : sqlite3_exec(hDB, pszSQL, nullptr, nullptr, nullptr));
1758 : }
1759 :
1760 3350 : if (!bSecureDeleteFound)
1761 : {
1762 : // Turn on secure_delete by default (unless the user specifies a
1763 : // value of this pragma through OGR_SQLITE_PRAGMA)
1764 : // For example, Debian and Conda-Forge SQLite3 builds already turn on
1765 : // secure_delete.
1766 3349 : CPL_IGNORE_RET_VAL(sqlite3_exec(hDB, "PRAGMA secure_delete = 1",
1767 : nullptr, nullptr, nullptr));
1768 : }
1769 :
1770 3350 : SetCacheSize();
1771 3350 : SetSynchronous();
1772 3350 : if (bLoadExtensions)
1773 1991 : LoadExtensions();
1774 :
1775 3350 : return true;
1776 : }
1777 :
1778 : /************************************************************************/
1779 : /* OpenOrCreateDB() */
1780 : /************************************************************************/
1781 :
1782 1365 : bool OGRSQLiteDataSource::OpenOrCreateDB(int flagsIn,
1783 : bool bRegisterOGR2SQLiteExtensions)
1784 : {
1785 : {
1786 : // Make sure that OGR2SQLITE_static_register() doesn't instantiate
1787 : // its default OGR2SQLITEModule. Let's do it ourselves just afterwards
1788 : //
1789 : CPLConfigOptionSetter oSetter("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO",
1790 1365 : false);
1791 1365 : if (!OGRSQLiteBaseDataSource::OpenOrCreateDB(
1792 : flagsIn, bRegisterOGR2SQLiteExtensions,
1793 : /*bLoadExtensions=*/false))
1794 : {
1795 6 : return false;
1796 : }
1797 : }
1798 2718 : if (bRegisterOGR2SQLiteExtensions &&
1799 : // Do not run OGR2SQLITE_Setup() if called from ogrsqlitexecute.sql
1800 : // that will do it with other datasets.
1801 1359 : CPLTestBool(CPLGetConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "YES")))
1802 : {
1803 : // Make sure this is done before registering our custom functions
1804 : // to allow overriding Spatialite.
1805 721 : InitSpatialite();
1806 :
1807 721 : m_poSQLiteModule = OGR2SQLITE_Setup(this, this);
1808 : }
1809 : // We need to do LoadExtensions() after OGR2SQLITE_Setup(), otherwise
1810 : // tests in ogr_virtualogr.py::test_ogr_sqlite_load_extensions_load_self()
1811 : // will crash when trying to load libgdal as an extension (which is an
1812 : // errour we catch, but only if OGR2SQLITEModule has been created by
1813 : // above OGR2SQLITE_Setup()
1814 1359 : LoadExtensions();
1815 :
1816 : const char *pszPreludeStatements =
1817 1359 : CSLFetchNameValue(papszOpenOptions, "PRELUDE_STATEMENTS");
1818 1359 : if (pszPreludeStatements)
1819 : {
1820 1 : if (SQLCommand(hDB, pszPreludeStatements) != OGRERR_NONE)
1821 0 : return false;
1822 : }
1823 :
1824 1359 : return true;
1825 : }
1826 :
1827 : /************************************************************************/
1828 : /* PostInitSpatialite() */
1829 : /************************************************************************/
1830 :
1831 1060 : void OGRSQLiteDataSource::PostInitSpatialite()
1832 : {
1833 : #ifdef HAVE_SPATIALITE
1834 : const char *pszSqlitePragma =
1835 1060 : CPLGetConfigOption("OGR_SQLITE_PRAGMA", nullptr);
1836 1060 : OGRErr eErr = OGRERR_NONE;
1837 0 : if ((!pszSqlitePragma || !strstr(pszSqlitePragma, "trusted_schema")) &&
1838 : // Older sqlite versions don't have this pragma
1839 2117 : SQLGetInteger(hDB, "PRAGMA trusted_schema", &eErr) == 0 &&
1840 1057 : eErr == OGRERR_NONE)
1841 : {
1842 : // Spatialite <= 5.1.0 doesn't declare its functions as SQLITE_INNOCUOUS
1843 2114 : if (IsSpatialiteLoaded() && SpatialiteRequiresTrustedSchemaOn() &&
1844 1057 : AreSpatialiteTriggersSafe())
1845 : {
1846 1057 : CPLDebug("SQLITE", "Setting PRAGMA trusted_schema = 1");
1847 1057 : SQLCommand(hDB, "PRAGMA trusted_schema = 1");
1848 : }
1849 : }
1850 : #endif
1851 1060 : }
1852 :
1853 : /************************************************************************/
1854 : /* SpatialiteRequiresTrustedSchemaOn() */
1855 : /************************************************************************/
1856 :
1857 1058 : bool OGRSQLiteBaseDataSource::SpatialiteRequiresTrustedSchemaOn()
1858 : {
1859 : #ifdef HAVE_SPATIALITE
1860 : // Spatialite <= 5.1.0 doesn't declare its functions as SQLITE_INNOCUOUS
1861 1058 : if (GetSpatialiteVersionNumber() <= MakeSpatialiteVersionNumber(5, 1, 0))
1862 : {
1863 1058 : return true;
1864 : }
1865 : #endif
1866 0 : return false;
1867 : }
1868 :
1869 : /************************************************************************/
1870 : /* AreSpatialiteTriggersSafe() */
1871 : /************************************************************************/
1872 :
1873 1058 : bool OGRSQLiteBaseDataSource::AreSpatialiteTriggersSafe()
1874 : {
1875 : #ifdef HAVE_SPATIALITE
1876 : // Not totally sure about the minimum spatialite version, but 4.3a is fine
1877 1058 : return GetSpatialiteVersionNumber() >=
1878 2116 : MakeSpatialiteVersionNumber(4, 3, 0) &&
1879 2116 : 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 385 : bool OGRSQLiteDataSource::Create(const char *pszNameIn, char **papszOptions)
1902 : {
1903 770 : CPLString osCommand;
1904 :
1905 : const bool bUseTempFile =
1906 385 : CPLTestBool(CPLGetConfigOption(
1907 386 : "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 385 : "FORCED"));
1912 :
1913 385 : 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 384 : m_pszFilename = CPLStrdup(pszNameIn);
1923 : }
1924 :
1925 : /* -------------------------------------------------------------------- */
1926 : /* Check that spatialite extensions are loaded if required to */
1927 : /* create a spatialite database */
1928 : /* -------------------------------------------------------------------- */
1929 385 : const bool bSpatialite = CPLFetchBool(papszOptions, "SPATIALITE", false);
1930 385 : 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 385 : m_bIsSpatiaLiteDB = bSpatialite;
1945 :
1946 : /* -------------------------------------------------------------------- */
1947 : /* Create the database file. */
1948 : /* -------------------------------------------------------------------- */
1949 385 : if (!OpenOrCreateDB(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, true))
1950 5 : return false;
1951 :
1952 : /* -------------------------------------------------------------------- */
1953 : /* Create the SpatiaLite metadata tables. */
1954 : /* -------------------------------------------------------------------- */
1955 380 : 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 305 : else if (bMetadata)
2012 : {
2013 296 : 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 296 : " 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 751 : if ((bSpatialite || bMetadata) &&
2036 371 : CPLFetchBool(papszOptions, "INIT_WITH_EPSG", false))
2037 : {
2038 2 : if (!InitWithEPSG())
2039 0 : return false;
2040 : }
2041 :
2042 760 : GDALOpenInfo oOpenInfo(m_pszFilename, GDAL_OF_VECTOR | GDAL_OF_UPDATE);
2043 380 : 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 636 : void OGRSQLiteDataSource::ReloadLayers()
2263 : {
2264 636 : m_apoLayers.clear();
2265 :
2266 636 : GDALOpenInfo oOpenInfo(m_pszFilename,
2267 1272 : GDAL_OF_VECTOR | (GetUpdate() ? GDAL_OF_UPDATE : 0));
2268 636 : Open(&oOpenInfo);
2269 636 : }
2270 :
2271 : /************************************************************************/
2272 : /* Open() */
2273 : /************************************************************************/
2274 :
2275 1999 : bool OGRSQLiteDataSource::Open(GDALOpenInfo *poOpenInfo)
2276 :
2277 : {
2278 1999 : const char *pszNewName = poOpenInfo->pszFilename;
2279 1999 : CPLAssert(m_apoLayers.empty());
2280 1999 : eAccess = poOpenInfo->eAccess;
2281 1999 : nOpenFlags = poOpenInfo->nOpenFlags & ~GDAL_OF_THREAD_SAFE;
2282 1999 : SetDescription(pszNewName);
2283 :
2284 1999 : 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 983 : if (STARTS_WITH_CI(pszNewName, "SQLITE:"))
2303 : {
2304 78 : m_pszFilename = CPLStrdup(pszNewName + strlen("SQLITE:"));
2305 : }
2306 : else
2307 : {
2308 905 : m_pszFilename = CPLStrdup(pszNewName);
2309 905 : if (poOpenInfo->pabyHeader &&
2310 869 : STARTS_WITH(
2311 : reinterpret_cast<const char *>(poOpenInfo->pabyHeader),
2312 : "SQLite format 3"))
2313 : {
2314 867 : m_bCallUndeclareFileNotToOpen = true;
2315 867 : GDALOpenInfoDeclareFileNotToOpen(m_pszFilename,
2316 867 : poOpenInfo->pabyHeader,
2317 : poOpenInfo->nHeaderBytes);
2318 : }
2319 : }
2320 : }
2321 1999 : SetPhysicalFilename(m_pszFilename);
2322 :
2323 : VSIStatBufL sStat;
2324 1999 : if (VSIStatL(m_pszFilename, &sStat) == 0)
2325 : {
2326 1944 : m_nFileTimestamp = sStat.st_mtime;
2327 : }
2328 :
2329 1999 : if (poOpenInfo->papszOpenOptions)
2330 : {
2331 11 : CSLDestroy(papszOpenOptions);
2332 11 : papszOpenOptions = CSLDuplicate(poOpenInfo->papszOpenOptions);
2333 : }
2334 :
2335 1999 : const bool bListVectorLayers = (nOpenFlags & GDAL_OF_VECTOR) != 0;
2336 :
2337 : const bool bListAllTables =
2338 3998 : bListVectorLayers &&
2339 3998 : CPLTestBool(CSLFetchNameValueDef(
2340 1999 : papszOpenOptions, "LIST_ALL_TABLES",
2341 1999 : 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 3998 : bListVectorLayers &&
2348 3998 : CPLTestBool(CSLFetchNameValueDef(
2349 1999 : papszOpenOptions, "LIST_VIRTUAL_OGR",
2350 1999 : CPLGetConfigOption("OGR_SQLITE_LIST_VIRTUAL_OGR", "NO")));
2351 :
2352 : /* -------------------------------------------------------------------- */
2353 : /* Try to open the sqlite database properly now. */
2354 : /* -------------------------------------------------------------------- */
2355 1999 : 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 983 : GDALOpenInfo oOpenInfo(m_pszFilename, GA_ReadOnly);
2366 983 : if (oOpenInfo.pabyHeader &&
2367 947 : (STARTS_WITH(
2368 : reinterpret_cast<const char *>(oOpenInfo.pabyHeader),
2369 946 : "-- SQL SQLITE") ||
2370 946 : STARTS_WITH(
2371 : reinterpret_cast<const char *>(oOpenInfo.pabyHeader),
2372 945 : "-- SQL RASTERLITE") ||
2373 945 : 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 983 : if (hDB == nullptr)
2493 : #endif
2494 : {
2495 980 : 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 845 : VSIFCloseL(poOpenInfo->fpL);
2500 845 : poOpenInfo->fpL = nullptr;
2501 : }
2502 980 : 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 982 : InitSpatialite();
2514 :
2515 982 : 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 1998 : CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
2536 :
2537 1998 : char **papszResult = nullptr;
2538 1998 : char *pszErrMsg = nullptr;
2539 1998 : int nRowCount = 0;
2540 1998 : int nColCount = 0;
2541 1998 : 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 1998 : if (rc == SQLITE_OK)
2550 : {
2551 533 : CPLDebug("SQLITE", "OGR style SQLite DB found !");
2552 :
2553 533 : m_bHaveGeometryColumns = true;
2554 :
2555 764 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2556 : {
2557 231 : char **papszRow = papszResult + iRow * 6 + 6;
2558 231 : const char *pszTableName = papszRow[0];
2559 231 : const char *pszGeomCol = papszRow[1];
2560 :
2561 231 : if (pszTableName == nullptr || pszGeomCol == nullptr)
2562 0 : continue;
2563 :
2564 462 : m_aoMapTableToSetOfGeomCols[pszTableName].insert(
2565 231 : CPLString(pszGeomCol).tolower());
2566 : }
2567 :
2568 761 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2569 : {
2570 231 : char **papszRow = papszResult + iRow * 6 + 6;
2571 231 : const char *pszTableName = papszRow[0];
2572 :
2573 231 : if (pszTableName == nullptr)
2574 0 : continue;
2575 :
2576 231 : if (GDALDataset::GetLayerByName(pszTableName) == nullptr)
2577 : {
2578 228 : const bool bRet = OpenTable(pszTableName, true, false,
2579 : /* bMayEmitError = */ true);
2580 228 : 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 228 : if (bListAllTables)
2590 2 : CPLHashSetInsert(hSet, CPLStrdup(pszTableName));
2591 : }
2592 :
2593 530 : sqlite3_free_table(papszResult);
2594 :
2595 : /* --------------------------------------------------------------------
2596 : */
2597 : /* Detect VirtualOGR layers */
2598 : /* --------------------------------------------------------------------
2599 : */
2600 530 : 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 530 : if (bListAllTables)
2639 1 : goto all_tables;
2640 :
2641 529 : CPLHashSetDestroy(hSet);
2642 :
2643 529 : 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 529 : return true;
2651 : }
2652 :
2653 : /* -------------------------------------------------------------------- */
2654 : /* Otherwise we can deal with SpatiaLite database. */
2655 : /* -------------------------------------------------------------------- */
2656 1465 : sqlite3_free(pszErrMsg);
2657 1465 : 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 1465 : if (rc != SQLITE_OK)
2666 : {
2667 : /* Test with SpatiaLite 4.0 schema */
2668 1451 : sqlite3_free(pszErrMsg);
2669 1451 : 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 1451 : if (rc == SQLITE_OK)
2679 : {
2680 1203 : m_bSpatialite4Layout = true;
2681 1203 : m_nUndefinedSRID = 0;
2682 : }
2683 : }
2684 :
2685 1465 : if (rc == SQLITE_OK)
2686 : {
2687 1217 : m_bIsSpatiaLiteDB = true;
2688 1217 : m_bHaveGeometryColumns = true;
2689 :
2690 1217 : int iSpatialiteVersion = -1;
2691 :
2692 : /* Only enables write-mode if linked against SpatiaLite */
2693 1217 : if (IsSpatialiteLoaded())
2694 : {
2695 1217 : 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 1217 : return false;
2707 : }
2708 :
2709 2384 : if (m_bSpatialite4Layout && GetUpdate() && iSpatialiteVersion > 0 &&
2710 1167 : 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 1217 : CPLDebug("SQLITE", "SpatiaLite%s DB found !",
2726 1217 : (m_bSpatialite4Layout) ? " v4" : "");
2727 : }
2728 :
2729 : // List RasterLite2 coverages, so as to avoid listing corresponding
2730 : // technical tables
2731 1217 : std::set<CPLString> aoSetTablesToIgnore;
2732 1217 : if (m_bSpatialite4Layout)
2733 : {
2734 1203 : char **papszResults2 = nullptr;
2735 1203 : int nRowCount2 = 0, nColCount2 = 0;
2736 1203 : 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 1203 : sqlite3_free_table(papszResults2);
2742 1203 : 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 1598 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2771 : {
2772 381 : char **papszRow = papszResult + iRow * 6 + 6;
2773 381 : const char *pszTableName = papszRow[0];
2774 381 : const char *pszGeomCol = papszRow[1];
2775 :
2776 381 : if (pszTableName == nullptr || pszGeomCol == nullptr)
2777 0 : continue;
2778 762 : if (!bListAllTables &&
2779 381 : cpl::contains(aoSetTablesToIgnore, pszTableName))
2780 : {
2781 0 : continue;
2782 : }
2783 :
2784 762 : m_aoMapTableToSetOfGeomCols[pszTableName].insert(
2785 381 : CPLString(pszGeomCol).tolower());
2786 : }
2787 :
2788 1598 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2789 : {
2790 381 : char **papszRow = papszResult + iRow * 6 + 6;
2791 381 : const char *pszTableName = papszRow[0];
2792 :
2793 381 : if (pszTableName == nullptr)
2794 0 : continue;
2795 762 : if (!bListAllTables &&
2796 381 : cpl::contains(aoSetTablesToIgnore, pszTableName))
2797 : {
2798 0 : continue;
2799 : }
2800 :
2801 381 : if (GDALDataset::GetLayerByName(pszTableName) == nullptr)
2802 374 : OpenTable(pszTableName, true, false,
2803 : /* bMayEmitError = */ true);
2804 381 : if (bListAllTables)
2805 0 : CPLHashSetInsert(hSet, CPLStrdup(pszTableName));
2806 : }
2807 :
2808 1217 : sqlite3_free_table(papszResult);
2809 1217 : papszResult = nullptr;
2810 :
2811 : /* --------------------------------------------------------------------
2812 : */
2813 : /* Detect VirtualShape, VirtualXL and VirtualOGR layers */
2814 : /* --------------------------------------------------------------------
2815 : */
2816 : rc =
2817 1217 : 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 1217 : if (rc == SQLITE_OK)
2824 : {
2825 4063 : for (int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++)
2826 : {
2827 2846 : char **papszRow = papszResult + iRow * 2 + 2;
2828 2846 : const char *pszName = papszRow[0];
2829 2846 : const char *pszSQL = papszRow[1];
2830 2846 : if (pszName == nullptr || pszSQL == nullptr)
2831 0 : continue;
2832 :
2833 5692 : if ((IsSpatialiteLoaded() && (strstr(pszSQL, "VirtualShape") ||
2834 5692 : 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 1217 : sqlite3_free_table(papszResult);
2852 1217 : papszResult = nullptr;
2853 :
2854 : /* --------------------------------------------------------------------
2855 : */
2856 : /* Detect spatial views */
2857 : /* --------------------------------------------------------------------
2858 : */
2859 :
2860 1217 : 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 1217 : if (rc == SQLITE_OK)
2867 : {
2868 1211 : 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 1206 : sqlite3_free_table(papszResult);
2889 : }
2890 :
2891 1217 : if (bListAllTables)
2892 0 : goto all_tables;
2893 :
2894 1217 : CPLHashSetDestroy(hSet);
2895 :
2896 1217 : 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 1217 : 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 6 : whileUnsealing(poLayer->GetLayerDefn())
3008 3 : ->SetGeomType(poGeom->getGeometryType());
3009 12 : delete poFeature;
3010 : }
3011 14 : poLayer->ResetReading();
3012 14 : return true;
3013 : }
3014 :
3015 0 : return false;
3016 : }
3017 :
3018 : /************************************************************************/
3019 : /* OpenTable() */
3020 : /************************************************************************/
3021 :
3022 2038 : bool OGRSQLiteDataSource::OpenTable(const char *pszTableName, bool bIsTable,
3023 : bool bIsVirtualShape, bool bMayEmitError)
3024 :
3025 : {
3026 : /* -------------------------------------------------------------------- */
3027 : /* Create the layer object. */
3028 : /* -------------------------------------------------------------------- */
3029 4076 : auto poLayer = std::make_unique<OGRSQLiteTableLayer>(this);
3030 2038 : if (poLayer->Initialize(pszTableName, bIsTable, bIsVirtualShape, false,
3031 2038 : bMayEmitError) != CE_None)
3032 : {
3033 293 : return false;
3034 : }
3035 :
3036 : /* -------------------------------------------------------------------- */
3037 : /* Add layer to data source layer list. */
3038 : /* -------------------------------------------------------------------- */
3039 1745 : m_apoLayers.push_back(std::move(poLayer));
3040 :
3041 : // Remove in case of error in the schema processing
3042 1745 : if (!DealWithOgrSchemaOpenOption(papszOpenOptions))
3043 : {
3044 4 : m_apoLayers.pop_back();
3045 4 : return false;
3046 : }
3047 :
3048 1741 : return true;
3049 : }
3050 :
3051 : /************************************************************************/
3052 : /* OpenView() */
3053 : /************************************************************************/
3054 :
3055 5 : bool OGRSQLiteDataSource::OpenView(const char *pszViewName,
3056 : const char *pszViewGeometry,
3057 : const char *pszViewRowid,
3058 : const char *pszTableName,
3059 : const char *pszGeometryColumn)
3060 :
3061 : {
3062 : /* -------------------------------------------------------------------- */
3063 : /* Create the layer object. */
3064 : /* -------------------------------------------------------------------- */
3065 10 : auto poLayer = std::make_unique<OGRSQLiteViewLayer>(this);
3066 :
3067 5 : if (poLayer->Initialize(pszViewName, pszViewGeometry, pszViewRowid,
3068 5 : pszTableName, pszGeometryColumn) != CE_None)
3069 : {
3070 0 : return false;
3071 : }
3072 :
3073 : /* -------------------------------------------------------------------- */
3074 : /* Add layer to data source layer list. */
3075 : /* -------------------------------------------------------------------- */
3076 5 : m_apoLayers.push_back(std::move(poLayer));
3077 :
3078 5 : return true;
3079 : }
3080 :
3081 : /************************************************************************/
3082 : /* TestCapability() */
3083 : /************************************************************************/
3084 :
3085 1367 : int OGRSQLiteDataSource::TestCapability(const char *pszCap)
3086 :
3087 : {
3088 1367 : if (EQUAL(pszCap, ODsCCreateLayer) || EQUAL(pszCap, ODsCDeleteLayer) ||
3089 1157 : EQUAL(pszCap, ODsCCreateGeomFieldAfterCreateLayer) ||
3090 1056 : EQUAL(pszCap, ODsCRandomLayerWrite) ||
3091 1053 : EQUAL(pszCap, GDsCAddRelationship))
3092 314 : return GetUpdate();
3093 1053 : else if (EQUAL(pszCap, ODsCCurveGeometries))
3094 564 : return !m_bIsSpatiaLiteDB;
3095 489 : else if (EQUAL(pszCap, ODsCMeasuredGeometries))
3096 466 : return TRUE;
3097 : else
3098 23 : return OGRSQLiteBaseDataSource::TestCapability(pszCap);
3099 : }
3100 :
3101 : /************************************************************************/
3102 : /* TestCapability() */
3103 : /************************************************************************/
3104 :
3105 258 : int OGRSQLiteBaseDataSource::TestCapability(const char *pszCap)
3106 : {
3107 258 : if (EQUAL(pszCap, ODsCTransactions))
3108 106 : return true;
3109 152 : else if (EQUAL(pszCap, ODsCZGeometries))
3110 8 : return true;
3111 : else
3112 144 : return GDALPamDataset::TestCapability(pszCap);
3113 : }
3114 :
3115 : /************************************************************************/
3116 : /* GetLayer() */
3117 : /************************************************************************/
3118 :
3119 20163 : OGRLayer *OGRSQLiteDataSource::GetLayer(int iLayer)
3120 :
3121 : {
3122 20163 : if (iLayer < 0 || iLayer >= static_cast<int>(m_apoLayers.size()))
3123 10 : return nullptr;
3124 : else
3125 20153 : return m_apoLayers[iLayer].get();
3126 : }
3127 :
3128 : /************************************************************************/
3129 : /* GetLayerByName() */
3130 : /************************************************************************/
3131 :
3132 1679 : OGRLayer *OGRSQLiteDataSource::GetLayerByName(const char *pszLayerName)
3133 :
3134 : {
3135 1679 : OGRLayer *poLayer = GDALDataset::GetLayerByName(pszLayerName);
3136 1679 : if (poLayer != nullptr)
3137 1019 : return poLayer;
3138 :
3139 660 : for (auto &poLayerIter : m_apoInvisibleLayers)
3140 : {
3141 0 : if (EQUAL(poLayerIter->GetName(), pszLayerName))
3142 0 : return poLayerIter.get();
3143 : }
3144 :
3145 1320 : std::string osName(pszLayerName);
3146 660 : bool bIsTable = true;
3147 957 : for (int i = 0; i < 2; i++)
3148 : {
3149 957 : char *pszSQL = sqlite3_mprintf("SELECT type FROM sqlite_master "
3150 : "WHERE type IN ('table', 'view') AND "
3151 : "lower(name) = lower('%q')",
3152 : osName.c_str());
3153 957 : int nRowCount = 0;
3154 957 : char **papszResult = nullptr;
3155 957 : CPL_IGNORE_RET_VAL(sqlite3_get_table(hDB, pszSQL, &papszResult,
3156 : &nRowCount, nullptr, nullptr));
3157 957 : if (papszResult && nRowCount == 1 && papszResult[1])
3158 366 : bIsTable = strcmp(papszResult[1], "table") == 0;
3159 957 : sqlite3_free_table(papszResult);
3160 957 : sqlite3_free(pszSQL);
3161 957 : if (i == 0 && nRowCount == 0)
3162 : {
3163 588 : const auto nParenthesis = osName.find('(');
3164 588 : if (nParenthesis != std::string::npos && osName.back() == ')')
3165 : {
3166 297 : osName.resize(nParenthesis);
3167 297 : continue;
3168 : }
3169 : }
3170 660 : break;
3171 : }
3172 :
3173 660 : if (!OpenTable(pszLayerName, bIsTable, /* bIsVirtualShape = */ false,
3174 : /* bMayEmitError = */ false))
3175 294 : return nullptr;
3176 :
3177 366 : poLayer = m_apoLayers.back().get();
3178 366 : CPLErrorReset();
3179 366 : CPLPushErrorHandler(CPLQuietErrorHandler);
3180 366 : poLayer->GetLayerDefn();
3181 366 : CPLPopErrorHandler();
3182 366 : if (CPLGetLastErrorType() != 0)
3183 : {
3184 290 : CPLErrorReset();
3185 290 : m_apoLayers.pop_back();
3186 290 : return nullptr;
3187 : }
3188 :
3189 76 : return poLayer;
3190 : }
3191 :
3192 : /************************************************************************/
3193 : /* IsLayerPrivate() */
3194 : /************************************************************************/
3195 :
3196 6 : bool OGRSQLiteDataSource::IsLayerPrivate(int iLayer) const
3197 : {
3198 6 : if (iLayer < 0 || iLayer >= static_cast<int>(m_apoLayers.size()))
3199 0 : return false;
3200 :
3201 12 : const std::string osName(m_apoLayers[iLayer]->GetName());
3202 12 : const CPLString osLCName(CPLString(osName).tolower());
3203 137 : for (const char *systemTableName : {"spatialindex",
3204 : "geom_cols_ref_sys",
3205 : "geometry_columns",
3206 : "geometry_columns_auth",
3207 : "views_geometry_column",
3208 : "virts_geometry_column",
3209 : "spatial_ref_sys",
3210 : "spatial_ref_sys_all",
3211 : "spatial_ref_sys_aux",
3212 : "sqlite_sequence",
3213 : "tableprefix_metadata",
3214 : "tableprefix_rasters",
3215 : "layer_params",
3216 : "layer_statistics",
3217 : "layer_sub_classes",
3218 : "layer_table_layout",
3219 : "pattern_bitmaps",
3220 : "symbol_bitmaps",
3221 : "project_defs",
3222 : "raster_pyramids",
3223 : "sqlite_stat1",
3224 : "sqlite_stat2",
3225 : "spatialite_history",
3226 : "geometry_columns_field_infos",
3227 : "geometry_columns_statistics",
3228 : "geometry_columns_time",
3229 : "sql_statements_log",
3230 : "vector_layers",
3231 : "vector_layers_auth",
3232 : "vector_layers_field_infos",
3233 : "vector_layers_statistics",
3234 : "views_geometry_columns_auth",
3235 : "views_geometry_columns_field_infos",
3236 : "views_geometry_columns_statistics",
3237 : "virts_geometry_columns_auth",
3238 : "virts_geometry_columns_field_infos",
3239 : "virts_geometry_columns_statistics",
3240 : "virts_layer_statistics",
3241 : "views_layer_statistics",
3242 143 : "elementarygeometries"})
3243 : {
3244 140 : if (osLCName == systemTableName)
3245 3 : return true;
3246 : }
3247 :
3248 3 : return false;
3249 : }
3250 :
3251 : /************************************************************************/
3252 : /* GetLayerByNameNotVisible() */
3253 : /************************************************************************/
3254 :
3255 : OGRLayer *
3256 4 : OGRSQLiteDataSource::GetLayerByNameNotVisible(const char *pszLayerName)
3257 :
3258 : {
3259 : {
3260 4 : OGRLayer *poLayer = GDALDataset::GetLayerByName(pszLayerName);
3261 4 : if (poLayer != nullptr)
3262 2 : return poLayer;
3263 : }
3264 :
3265 2 : for (auto &poLayerIter : m_apoInvisibleLayers)
3266 : {
3267 0 : if (EQUAL(poLayerIter->GetName(), pszLayerName))
3268 0 : return poLayerIter.get();
3269 : }
3270 :
3271 : /* -------------------------------------------------------------------- */
3272 : /* Create the layer object. */
3273 : /* -------------------------------------------------------------------- */
3274 4 : auto poLayer = std::make_unique<OGRSQLiteTableLayer>(this);
3275 2 : if (poLayer->Initialize(pszLayerName, true, false, false,
3276 2 : /* bMayEmitError = */ true) != CE_None)
3277 : {
3278 0 : return nullptr;
3279 : }
3280 2 : CPLErrorReset();
3281 2 : CPLPushErrorHandler(CPLQuietErrorHandler);
3282 2 : poLayer->GetLayerDefn();
3283 2 : CPLPopErrorHandler();
3284 2 : if (CPLGetLastErrorType() != 0)
3285 : {
3286 0 : CPLErrorReset();
3287 0 : return nullptr;
3288 : }
3289 2 : m_apoInvisibleLayers.push_back(std::move(poLayer));
3290 :
3291 2 : return m_apoInvisibleLayers.back().get();
3292 : }
3293 :
3294 : /************************************************************************/
3295 : /* GetLayerWithGetSpatialWhereByName() */
3296 : /************************************************************************/
3297 :
3298 : std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>
3299 584 : OGRSQLiteDataSource::GetLayerWithGetSpatialWhereByName(const char *pszName)
3300 : {
3301 : OGRSQLiteLayer *poRet =
3302 584 : cpl::down_cast<OGRSQLiteLayer *>(GetLayerByName(pszName));
3303 584 : return std::pair<OGRLayer *, IOGRSQLiteGetSpatialWhere *>(poRet, poRet);
3304 : }
3305 :
3306 : /************************************************************************/
3307 : /* FlushCache() */
3308 : /************************************************************************/
3309 :
3310 1419 : CPLErr OGRSQLiteDataSource::FlushCache(bool bAtClosing)
3311 : {
3312 1419 : CPLErr eErr = CE_None;
3313 3504 : for (auto &poLayer : m_apoLayers)
3314 : {
3315 2085 : if (poLayer->IsTableLayer())
3316 : {
3317 : OGRSQLiteTableLayer *poTableLayer =
3318 2078 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3319 2078 : if (poTableLayer->RunDeferredCreationIfNecessary() != OGRERR_NONE)
3320 0 : eErr = CE_Failure;
3321 2078 : poTableLayer->CreateSpatialIndexIfNecessary();
3322 : }
3323 : }
3324 1419 : if (GDALDataset::FlushCache(bAtClosing) != CE_None)
3325 0 : eErr = CE_Failure;
3326 1419 : return eErr;
3327 : }
3328 :
3329 : /************************************************************************/
3330 : /* ExecuteSQL() */
3331 : /************************************************************************/
3332 :
3333 : static const char *const apszFuncsWithSideEffects[] = {
3334 : "InitSpatialMetaData", "AddGeometryColumn",
3335 : "RecoverGeometryColumn", "DiscardGeometryColumn",
3336 : "CreateSpatialIndex", "CreateMbrCache",
3337 : "DisableSpatialIndex", "UpdateLayerStatistics",
3338 :
3339 : "ogr_datasource_load_layers"};
3340 :
3341 1609 : OGRLayer *OGRSQLiteDataSource::ExecuteSQL(const char *pszSQLCommand,
3342 : OGRGeometry *poSpatialFilter,
3343 : const char *pszDialect)
3344 :
3345 : {
3346 7540 : for (auto &poLayer : m_apoLayers)
3347 : {
3348 5931 : if (poLayer->IsTableLayer())
3349 : {
3350 : OGRSQLiteTableLayer *poTableLayer =
3351 5927 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3352 5927 : poTableLayer->RunDeferredCreationIfNecessary();
3353 5927 : poTableLayer->CreateSpatialIndexIfNecessary();
3354 : }
3355 : }
3356 :
3357 1609 : if (pszDialect != nullptr && EQUAL(pszDialect, "INDIRECT_SQLITE"))
3358 0 : return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter,
3359 0 : "SQLITE");
3360 1609 : else if (pszDialect != nullptr && !EQUAL(pszDialect, "") &&
3361 2 : !EQUAL(pszDialect, "NATIVE") && !EQUAL(pszDialect, "SQLITE"))
3362 :
3363 2 : return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter,
3364 2 : pszDialect);
3365 :
3366 1607 : if (EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like = 0") ||
3367 1606 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like=0") ||
3368 1606 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like =0") ||
3369 1606 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like= 0"))
3370 : {
3371 1 : if (m_poSQLiteModule)
3372 1 : OGR2SQLITE_SetCaseSensitiveLike(m_poSQLiteModule, false);
3373 : }
3374 1606 : else if (EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like = 1") ||
3375 1605 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like=1") ||
3376 1605 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like =1") ||
3377 1605 : EQUAL(pszSQLCommand, "PRAGMA case_sensitive_like= 1"))
3378 : {
3379 1 : if (m_poSQLiteModule)
3380 1 : OGR2SQLITE_SetCaseSensitiveLike(m_poSQLiteModule, true);
3381 : }
3382 :
3383 : /* -------------------------------------------------------------------- */
3384 : /* Special case DELLAYER: command. */
3385 : /* -------------------------------------------------------------------- */
3386 1607 : if (STARTS_WITH_CI(pszSQLCommand, "DELLAYER:"))
3387 : {
3388 1 : const char *pszLayerName = pszSQLCommand + 9;
3389 :
3390 1 : while (*pszLayerName == ' ')
3391 0 : pszLayerName++;
3392 :
3393 1 : DeleteLayer(pszLayerName);
3394 1 : return nullptr;
3395 : }
3396 :
3397 : /* -------------------------------------------------------------------- */
3398 : /* Special case for SQLITE_HAS_COLUMN_METADATA() */
3399 : /* -------------------------------------------------------------------- */
3400 1606 : if (strcmp(pszSQLCommand, "SQLITE_HAS_COLUMN_METADATA()") == 0)
3401 : {
3402 : #ifdef SQLITE_HAS_COLUMN_METADATA
3403 : return new OGRSQLiteSingleFeatureLayer("SQLITE_HAS_COLUMN_METADATA",
3404 2 : TRUE);
3405 : #else
3406 : return new OGRSQLiteSingleFeatureLayer("SQLITE_HAS_COLUMN_METADATA",
3407 : FALSE);
3408 : #endif
3409 : }
3410 :
3411 : /* -------------------------------------------------------------------- */
3412 : /* In case, this is not a SELECT, invalidate cached feature */
3413 : /* count and extent to be on the safe side. */
3414 : /* -------------------------------------------------------------------- */
3415 1604 : if (EQUAL(pszSQLCommand, "VACUUM"))
3416 : {
3417 1 : int nNeedRefresh = -1;
3418 1 : for (auto &poLayer : m_apoLayers)
3419 : {
3420 1 : if (poLayer->IsTableLayer())
3421 : {
3422 : OGRSQLiteTableLayer *poTableLayer =
3423 1 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3424 1 : if (!(poTableLayer->AreStatisticsValid()) ||
3425 0 : poTableLayer->DoStatisticsNeedToBeFlushed())
3426 : {
3427 1 : nNeedRefresh = FALSE;
3428 1 : break;
3429 : }
3430 0 : else if (nNeedRefresh < 0)
3431 0 : nNeedRefresh = TRUE;
3432 : }
3433 : }
3434 1 : if (nNeedRefresh == TRUE)
3435 : {
3436 0 : for (auto &poLayer : m_apoLayers)
3437 : {
3438 0 : if (poLayer->IsTableLayer())
3439 : {
3440 : OGRSQLiteTableLayer *poTableLayer =
3441 0 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3442 0 : poTableLayer->ForceStatisticsToBeFlushed();
3443 : }
3444 : }
3445 : }
3446 : }
3447 1603 : else if (ProcessTransactionSQL(pszSQLCommand))
3448 : {
3449 315 : return nullptr;
3450 : }
3451 1288 : else if (!STARTS_WITH_CI(pszSQLCommand, "SELECT ") &&
3452 198 : !STARTS_WITH_CI(pszSQLCommand, "CREATE TABLE ") &&
3453 113 : !STARTS_WITH_CI(pszSQLCommand, "PRAGMA "))
3454 : {
3455 153 : for (auto &poLayer : m_apoLayers)
3456 50 : poLayer->InvalidateCachedFeatureCountAndExtent();
3457 : }
3458 :
3459 1289 : m_bLastSQLCommandIsUpdateLayerStatistics =
3460 1289 : EQUAL(pszSQLCommand, "SELECT UpdateLayerStatistics()");
3461 :
3462 : /* -------------------------------------------------------------------- */
3463 : /* Prepare statement. */
3464 : /* -------------------------------------------------------------------- */
3465 1289 : sqlite3_stmt *hSQLStmt = nullptr;
3466 :
3467 2578 : CPLString osSQLCommand = pszSQLCommand;
3468 :
3469 : /* This will speed-up layer creation */
3470 : /* ORDER BY are costly to evaluate and are not necessary to establish */
3471 : /* the layer definition. */
3472 1289 : bool bUseStatementForGetNextFeature = true;
3473 1289 : bool bEmptyLayer = false;
3474 :
3475 6047 : if (osSQLCommand.ifind("SELECT ") == 0 &&
3476 2379 : CPLString(osSQLCommand.substr(1)).ifind("SELECT ") ==
3477 967 : std::string::npos &&
3478 967 : osSQLCommand.ifind(" UNION ") == std::string::npos &&
3479 3346 : osSQLCommand.ifind(" INTERSECT ") == std::string::npos &&
3480 967 : osSQLCommand.ifind(" EXCEPT ") == std::string::npos)
3481 : {
3482 967 : size_t nOrderByPos = osSQLCommand.ifind(" ORDER BY ");
3483 967 : if (nOrderByPos != std::string::npos)
3484 : {
3485 54 : osSQLCommand.resize(nOrderByPos);
3486 54 : bUseStatementForGetNextFeature = false;
3487 : }
3488 : }
3489 :
3490 : int rc =
3491 1289 : prepareSql(GetDB(), osSQLCommand.c_str(),
3492 1289 : static_cast<int>(osSQLCommand.size()), &hSQLStmt, nullptr);
3493 :
3494 1289 : if (rc != SQLITE_OK)
3495 : {
3496 16 : CPLError(CE_Failure, CPLE_AppDefined,
3497 : "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n %s",
3498 : osSQLCommand.c_str(), sqlite3_errmsg(GetDB()));
3499 :
3500 16 : if (hSQLStmt != nullptr)
3501 : {
3502 0 : sqlite3_finalize(hSQLStmt);
3503 : }
3504 :
3505 16 : return nullptr;
3506 : }
3507 :
3508 : /* -------------------------------------------------------------------- */
3509 : /* Do we get a resultset? */
3510 : /* -------------------------------------------------------------------- */
3511 1273 : rc = sqlite3_step(hSQLStmt);
3512 1273 : if (rc != SQLITE_ROW)
3513 : {
3514 363 : if (rc != SQLITE_DONE)
3515 : {
3516 20 : CPLError(CE_Failure, CPLE_AppDefined,
3517 : "In ExecuteSQL(): sqlite3_step(%s):\n %s",
3518 : osSQLCommand.c_str(), sqlite3_errmsg(GetDB()));
3519 :
3520 20 : sqlite3_finalize(hSQLStmt);
3521 20 : return nullptr;
3522 : }
3523 :
3524 343 : if (STARTS_WITH_CI(pszSQLCommand, "CREATE "))
3525 : {
3526 113 : char **papszTokens = CSLTokenizeString(pszSQLCommand);
3527 113 : if (CSLCount(papszTokens) >= 4 &&
3528 124 : EQUAL(papszTokens[1], "VIRTUAL") &&
3529 11 : EQUAL(papszTokens[2], "TABLE"))
3530 : {
3531 11 : OpenVirtualTable(papszTokens[3], pszSQLCommand);
3532 : }
3533 113 : CSLDestroy(papszTokens);
3534 :
3535 113 : sqlite3_finalize(hSQLStmt);
3536 113 : return nullptr;
3537 : }
3538 :
3539 230 : if (!STARTS_WITH_CI(pszSQLCommand, "SELECT "))
3540 : {
3541 63 : sqlite3_finalize(hSQLStmt);
3542 63 : return nullptr;
3543 : }
3544 :
3545 167 : bUseStatementForGetNextFeature = false;
3546 167 : bEmptyLayer = true;
3547 : }
3548 :
3549 : /* -------------------------------------------------------------------- */
3550 : /* Special case for some functions which must be run */
3551 : /* only once */
3552 : /* -------------------------------------------------------------------- */
3553 1077 : if (STARTS_WITH_CI(pszSQLCommand, "SELECT "))
3554 : {
3555 10256 : for (unsigned int i = 0; i < sizeof(apszFuncsWithSideEffects) /
3556 : sizeof(apszFuncsWithSideEffects[0]);
3557 : i++)
3558 : {
3559 9281 : if (EQUALN(apszFuncsWithSideEffects[i], pszSQLCommand + 7,
3560 : strlen(apszFuncsWithSideEffects[i])))
3561 : {
3562 188 : if (sqlite3_column_count(hSQLStmt) == 1 &&
3563 94 : sqlite3_column_type(hSQLStmt, 0) == SQLITE_INTEGER)
3564 : {
3565 94 : const int ret = sqlite3_column_int(hSQLStmt, 0);
3566 :
3567 94 : sqlite3_finalize(hSQLStmt);
3568 :
3569 : return new OGRSQLiteSingleFeatureLayer(
3570 94 : apszFuncsWithSideEffects[i], ret);
3571 : }
3572 : }
3573 : }
3574 : }
3575 :
3576 : /* -------------------------------------------------------------------- */
3577 : /* Create layer. */
3578 : /* -------------------------------------------------------------------- */
3579 :
3580 983 : CPLString osSQL = pszSQLCommand;
3581 : OGRSQLiteSelectLayer *poLayer = new OGRSQLiteSelectLayer(
3582 : this, osSQL, hSQLStmt, bUseStatementForGetNextFeature, bEmptyLayer,
3583 983 : true, /*bCanReopenBaseDS=*/true);
3584 :
3585 986 : if (poSpatialFilter != nullptr &&
3586 3 : poLayer->GetLayerDefn()->GetGeomFieldCount() > 0)
3587 0 : poLayer->SetSpatialFilter(0, poSpatialFilter);
3588 :
3589 983 : return poLayer;
3590 : }
3591 :
3592 : /************************************************************************/
3593 : /* ReleaseResultSet() */
3594 : /************************************************************************/
3595 :
3596 1074 : void OGRSQLiteDataSource::ReleaseResultSet(OGRLayer *poLayer)
3597 :
3598 : {
3599 1074 : delete poLayer;
3600 1074 : }
3601 :
3602 : /************************************************************************/
3603 : /* ICreateLayer() */
3604 : /************************************************************************/
3605 :
3606 : OGRLayer *
3607 432 : OGRSQLiteDataSource::ICreateLayer(const char *pszLayerNameIn,
3608 : const OGRGeomFieldDefn *poGeomFieldDefn,
3609 : CSLConstList papszOptions)
3610 :
3611 : {
3612 : /* -------------------------------------------------------------------- */
3613 : /* Verify we are in update mode. */
3614 : /* -------------------------------------------------------------------- */
3615 432 : char *pszLayerName = nullptr;
3616 432 : if (!GetUpdate())
3617 : {
3618 1 : CPLError(CE_Failure, CPLE_NoWriteAccess,
3619 : "Data source %s opened read-only.\n"
3620 : "New layer %s cannot be created.\n",
3621 : m_pszFilename, pszLayerNameIn);
3622 :
3623 1 : return nullptr;
3624 : }
3625 :
3626 431 : const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
3627 : const auto poSRS =
3628 431 : poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
3629 :
3630 431 : if (m_bIsSpatiaLiteDB && eType != wkbNone)
3631 : {
3632 : // We need to catch this right now as AddGeometryColumn does not
3633 : // return an error
3634 144 : OGRwkbGeometryType eFType = wkbFlatten(eType);
3635 144 : if (eFType > wkbGeometryCollection)
3636 : {
3637 0 : CPLError(CE_Failure, CPLE_NotSupported,
3638 : "Cannot create geometry field of type %s",
3639 : OGRToOGCGeomType(eType));
3640 0 : return nullptr;
3641 : }
3642 : }
3643 :
3644 4054 : for (auto &poLayer : m_apoLayers)
3645 : {
3646 3623 : if (poLayer->IsTableLayer())
3647 : {
3648 : OGRSQLiteTableLayer *poTableLayer =
3649 3623 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
3650 3623 : poTableLayer->RunDeferredCreationIfNecessary();
3651 : }
3652 : }
3653 :
3654 862 : CPLString osFIDColumnName;
3655 : const char *pszFIDColumnNameIn =
3656 431 : CSLFetchNameValueDef(papszOptions, "FID", "OGC_FID");
3657 431 : if (CPLFetchBool(papszOptions, "LAUNDER", true))
3658 : {
3659 430 : char *pszFIDColumnName = LaunderName(pszFIDColumnNameIn);
3660 430 : osFIDColumnName = pszFIDColumnName;
3661 430 : CPLFree(pszFIDColumnName);
3662 : }
3663 : else
3664 1 : osFIDColumnName = pszFIDColumnNameIn;
3665 :
3666 431 : if (CPLFetchBool(papszOptions, "LAUNDER", true))
3667 430 : pszLayerName = LaunderName(pszLayerNameIn);
3668 : else
3669 1 : pszLayerName = CPLStrdup(pszLayerNameIn);
3670 :
3671 431 : const char *pszGeomFormat = CSLFetchNameValue(papszOptions, "FORMAT");
3672 431 : if (pszGeomFormat == nullptr)
3673 : {
3674 426 : if (!m_bIsSpatiaLiteDB)
3675 278 : pszGeomFormat = "WKB";
3676 : else
3677 148 : pszGeomFormat = "SpatiaLite";
3678 : }
3679 :
3680 431 : if (!EQUAL(pszGeomFormat, "WKT") && !EQUAL(pszGeomFormat, "WKB") &&
3681 150 : !EQUAL(pszGeomFormat, "SpatiaLite"))
3682 : {
3683 1 : CPLError(CE_Failure, CPLE_NotSupported,
3684 : "FORMAT=%s not recognised or supported.", pszGeomFormat);
3685 1 : CPLFree(pszLayerName);
3686 1 : return nullptr;
3687 : }
3688 :
3689 860 : CPLString osGeometryName;
3690 : const char *pszGeometryNameIn =
3691 430 : CSLFetchNameValue(papszOptions, "GEOMETRY_NAME");
3692 430 : if (pszGeometryNameIn == nullptr)
3693 : {
3694 : osGeometryName =
3695 390 : (EQUAL(pszGeomFormat, "WKT")) ? "WKT_GEOMETRY" : "GEOMETRY";
3696 : }
3697 : else
3698 : {
3699 40 : if (CPLFetchBool(papszOptions, "LAUNDER", true))
3700 : {
3701 40 : char *pszGeometryName = LaunderName(pszGeometryNameIn);
3702 40 : osGeometryName = pszGeometryName;
3703 40 : CPLFree(pszGeometryName);
3704 : }
3705 : else
3706 0 : osGeometryName = pszGeometryNameIn;
3707 : }
3708 :
3709 430 : if (m_bIsSpatiaLiteDB && !EQUAL(pszGeomFormat, "SpatiaLite"))
3710 : {
3711 1 : CPLError(CE_Failure, CPLE_NotSupported,
3712 : "FORMAT=%s not supported on a SpatiaLite enabled database.",
3713 : pszGeomFormat);
3714 1 : CPLFree(pszLayerName);
3715 1 : return nullptr;
3716 : }
3717 :
3718 : // Should not happen since a spatialite DB should be opened in
3719 : // read-only mode if libspatialite is not loaded.
3720 429 : if (m_bIsSpatiaLiteDB && !IsSpatialiteLoaded())
3721 : {
3722 0 : CPLError(CE_Failure, CPLE_NotSupported,
3723 : "Creating layers on a SpatiaLite enabled database, "
3724 : "without Spatialite extensions loaded, is not supported.");
3725 0 : CPLFree(pszLayerName);
3726 0 : return nullptr;
3727 : }
3728 :
3729 : /* -------------------------------------------------------------------- */
3730 : /* Do we already have this layer? If so, should we blow it */
3731 : /* away? */
3732 : /* -------------------------------------------------------------------- */
3733 4050 : for (auto &poLayer : m_apoLayers)
3734 : {
3735 3623 : if (EQUAL(pszLayerName, poLayer->GetLayerDefn()->GetName()))
3736 : {
3737 3 : if (CSLFetchNameValue(papszOptions, "OVERWRITE") != nullptr &&
3738 1 : !EQUAL(CSLFetchNameValue(papszOptions, "OVERWRITE"), "NO"))
3739 : {
3740 1 : DeleteLayer(pszLayerName);
3741 1 : break;
3742 : }
3743 : else
3744 : {
3745 1 : CPLError(CE_Failure, CPLE_AppDefined,
3746 : "Layer %s already exists, CreateLayer failed.\n"
3747 : "Use the layer creation option OVERWRITE=YES to "
3748 : "replace it.",
3749 : pszLayerName);
3750 1 : CPLFree(pszLayerName);
3751 1 : return nullptr;
3752 : }
3753 : }
3754 : }
3755 :
3756 : /* -------------------------------------------------------------------- */
3757 : /* Try to get the SRS Id of this spatial reference system, */
3758 : /* adding to the srs table if needed. */
3759 : /* -------------------------------------------------------------------- */
3760 428 : int nSRSId = m_nUndefinedSRID;
3761 428 : const char *pszSRID = CSLFetchNameValue(papszOptions, "SRID");
3762 :
3763 428 : if (pszSRID != nullptr && pszSRID[0] != '\0')
3764 : {
3765 4 : nSRSId = atoi(pszSRID);
3766 4 : if (nSRSId > 0)
3767 : {
3768 4 : OGRSpatialReference *poSRSFetched = FetchSRS(nSRSId);
3769 4 : if (poSRSFetched == nullptr)
3770 : {
3771 2 : CPLError(CE_Warning, CPLE_AppDefined,
3772 : "SRID %d will be used, but no matching SRS is defined "
3773 : "in spatial_ref_sys",
3774 : nSRSId);
3775 : }
3776 4 : }
3777 : }
3778 424 : else if (poSRS != nullptr)
3779 112 : nSRSId = FetchSRSId(poSRS);
3780 :
3781 428 : bool bImmediateSpatialIndexCreation = false;
3782 428 : bool bDeferredSpatialIndexCreation = false;
3783 :
3784 428 : const char *pszSI = CSLFetchNameValue(papszOptions, "SPATIAL_INDEX");
3785 428 : if (m_bHaveGeometryColumns && eType != wkbNone)
3786 : {
3787 0 : if (pszSI != nullptr && CPLTestBool(pszSI) &&
3788 304 : (m_bIsSpatiaLiteDB || EQUAL(pszGeomFormat, "SpatiaLite")) &&
3789 0 : !IsSpatialiteLoaded())
3790 : {
3791 0 : CPLError(CE_Warning, CPLE_OpenFailed,
3792 : "Cannot create a spatial index when Spatialite extensions "
3793 : "are not loaded.");
3794 : }
3795 :
3796 : #ifdef HAVE_SPATIALITE
3797 : /* Only if linked against SpatiaLite and the datasource was created as a
3798 : * SpatiaLite DB */
3799 304 : if (m_bIsSpatiaLiteDB && IsSpatialiteLoaded())
3800 : #else
3801 : if (0)
3802 : #endif
3803 : {
3804 143 : if (pszSI != nullptr && EQUAL(pszSI, "IMMEDIATE"))
3805 : {
3806 0 : bImmediateSpatialIndexCreation = true;
3807 : }
3808 143 : else if (pszSI == nullptr || CPLTestBool(pszSI))
3809 : {
3810 143 : bDeferredSpatialIndexCreation = true;
3811 : }
3812 : }
3813 : }
3814 124 : else if (m_bHaveGeometryColumns)
3815 : {
3816 : #ifdef HAVE_SPATIALITE
3817 115 : if (m_bIsSpatiaLiteDB && IsSpatialiteLoaded() &&
3818 0 : (pszSI == nullptr || CPLTestBool(pszSI)))
3819 5 : bDeferredSpatialIndexCreation = true;
3820 : #endif
3821 : }
3822 :
3823 : /* -------------------------------------------------------------------- */
3824 : /* Create the layer object. */
3825 : /* -------------------------------------------------------------------- */
3826 856 : auto poLayer = std::make_unique<OGRSQLiteTableLayer>(this);
3827 :
3828 428 : poLayer->Initialize(pszLayerName, true, false, true,
3829 : /* bMayEmitError = */ false);
3830 428 : OGRSpatialReference *poSRSClone = nullptr;
3831 428 : if (poSRS)
3832 : {
3833 112 : poSRSClone = poSRS->Clone();
3834 112 : poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
3835 : }
3836 428 : poLayer->SetCreationParameters(osFIDColumnName, eType, pszGeomFormat,
3837 : osGeometryName, poSRSClone, nSRSId);
3838 428 : if (poSRSClone)
3839 112 : poSRSClone->Release();
3840 :
3841 428 : poLayer->InitFeatureCount();
3842 428 : poLayer->SetLaunderFlag(CPLFetchBool(papszOptions, "LAUNDER", true));
3843 428 : if (CPLFetchBool(papszOptions, "COMPRESS_GEOM", false))
3844 47 : poLayer->SetUseCompressGeom(true);
3845 428 : if (bImmediateSpatialIndexCreation)
3846 0 : poLayer->CreateSpatialIndex(0);
3847 428 : else if (bDeferredSpatialIndexCreation)
3848 148 : poLayer->SetDeferredSpatialIndexCreation(true);
3849 428 : poLayer->SetCompressedColumns(
3850 : CSLFetchNameValue(papszOptions, "COMPRESS_COLUMNS"));
3851 428 : poLayer->SetStrictFlag(CPLFetchBool(papszOptions, "STRICT", false));
3852 :
3853 428 : CPLFree(pszLayerName);
3854 :
3855 : /* -------------------------------------------------------------------- */
3856 : /* Add layer to data source layer list. */
3857 : /* -------------------------------------------------------------------- */
3858 428 : m_apoLayers.push_back(std::move(poLayer));
3859 :
3860 428 : return m_apoLayers.back().get();
3861 : }
3862 :
3863 : /************************************************************************/
3864 : /* LaunderName() */
3865 : /************************************************************************/
3866 :
3867 2129 : char *OGRSQLiteDataSource::LaunderName(const char *pszSrcName)
3868 :
3869 : {
3870 2129 : char *pszSafeName = CPLStrdup(pszSrcName);
3871 21894 : for (int i = 0; pszSafeName[i] != '\0'; i++)
3872 : {
3873 19765 : pszSafeName[i] = static_cast<char>(
3874 19765 : CPLTolower(static_cast<unsigned char>(pszSafeName[i])));
3875 19765 : if (pszSafeName[i] == '\'' || pszSafeName[i] == '-' ||
3876 19765 : pszSafeName[i] == '#')
3877 0 : pszSafeName[i] = '_';
3878 : }
3879 :
3880 2129 : return pszSafeName;
3881 : }
3882 :
3883 : /************************************************************************/
3884 : /* DeleteLayer() */
3885 : /************************************************************************/
3886 :
3887 2 : void OGRSQLiteDataSource::DeleteLayer(const char *pszLayerName)
3888 :
3889 : {
3890 : /* -------------------------------------------------------------------- */
3891 : /* Verify we are in update mode. */
3892 : /* -------------------------------------------------------------------- */
3893 2 : if (!GetUpdate())
3894 : {
3895 0 : CPLError(CE_Failure, CPLE_NoWriteAccess,
3896 : "Data source %s opened read-only.\n"
3897 : "Layer %s cannot be deleted.\n",
3898 : m_pszFilename, pszLayerName);
3899 :
3900 0 : return;
3901 : }
3902 :
3903 : /* -------------------------------------------------------------------- */
3904 : /* Try to find layer. */
3905 : /* -------------------------------------------------------------------- */
3906 2 : int iLayer = 0; // Used after for.
3907 :
3908 2 : for (; iLayer < static_cast<int>(m_apoLayers.size()); iLayer++)
3909 : {
3910 2 : if (EQUAL(pszLayerName, m_apoLayers[iLayer]->GetLayerDefn()->GetName()))
3911 2 : break;
3912 : }
3913 :
3914 2 : if (iLayer == static_cast<int>(m_apoLayers.size()))
3915 : {
3916 0 : CPLError(
3917 : CE_Failure, CPLE_AppDefined,
3918 : "Attempt to delete layer '%s', but this layer is not known to OGR.",
3919 : pszLayerName);
3920 0 : return;
3921 : }
3922 :
3923 2 : DeleteLayer(iLayer);
3924 : }
3925 :
3926 : /************************************************************************/
3927 : /* DeleteLayer() */
3928 : /************************************************************************/
3929 :
3930 34 : OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
3931 : {
3932 34 : if (iLayer < 0 || iLayer >= static_cast<int>(m_apoLayers.size()))
3933 : {
3934 0 : CPLError(CE_Failure, CPLE_AppDefined,
3935 : "Layer %d not in legal range of 0 to %d.", iLayer,
3936 0 : static_cast<int>(m_apoLayers.size()) - 1);
3937 0 : return OGRERR_FAILURE;
3938 : }
3939 :
3940 68 : CPLString osLayerName = GetLayer(iLayer)->GetName();
3941 68 : CPLString osGeometryColumn = GetLayer(iLayer)->GetGeometryColumn();
3942 :
3943 : /* -------------------------------------------------------------------- */
3944 : /* Blow away our OGR structures related to the layer. This is */
3945 : /* pretty dangerous if anything has a reference to this layer! */
3946 : /* -------------------------------------------------------------------- */
3947 34 : CPLDebug("OGR_SQLITE", "DeleteLayer(%s)", osLayerName.c_str());
3948 :
3949 34 : m_apoLayers.erase(m_apoLayers.begin() + iLayer);
3950 :
3951 : /* -------------------------------------------------------------------- */
3952 : /* Remove from the database. */
3953 : /* -------------------------------------------------------------------- */
3954 68 : CPLString osEscapedLayerName = SQLEscapeLiteral(osLayerName);
3955 34 : const char *pszEscapedLayerName = osEscapedLayerName.c_str();
3956 : const char *pszGeometryColumn =
3957 34 : osGeometryColumn.size() ? osGeometryColumn.c_str() : nullptr;
3958 :
3959 34 : if (SQLCommand(hDB, CPLSPrintf("DROP TABLE '%s'", pszEscapedLayerName)) !=
3960 : OGRERR_NONE)
3961 : {
3962 0 : return OGRERR_FAILURE;
3963 : }
3964 :
3965 : /* -------------------------------------------------------------------- */
3966 : /* Drop from geometry_columns table. */
3967 : /* -------------------------------------------------------------------- */
3968 34 : if (m_bHaveGeometryColumns)
3969 : {
3970 34 : CPLString osCommand;
3971 :
3972 : osCommand.Printf(
3973 : "DELETE FROM geometry_columns WHERE f_table_name = '%s'",
3974 34 : pszEscapedLayerName);
3975 :
3976 34 : if (SQLCommand(hDB, osCommand) != OGRERR_NONE)
3977 : {
3978 0 : return OGRERR_FAILURE;
3979 : }
3980 :
3981 : /* --------------------------------------------------------------------
3982 : */
3983 : /* Drop spatialite spatial index tables */
3984 : /* --------------------------------------------------------------------
3985 : */
3986 34 : if (m_bIsSpatiaLiteDB && pszGeometryColumn)
3987 : {
3988 : osCommand.Printf("DROP TABLE 'idx_%s_%s'", pszEscapedLayerName,
3989 15 : SQLEscapeLiteral(pszGeometryColumn).c_str());
3990 15 : CPL_IGNORE_RET_VAL(
3991 15 : sqlite3_exec(hDB, osCommand, nullptr, nullptr, nullptr));
3992 :
3993 : osCommand.Printf("DROP TABLE 'idx_%s_%s_node'", pszEscapedLayerName,
3994 15 : SQLEscapeLiteral(pszGeometryColumn).c_str());
3995 15 : CPL_IGNORE_RET_VAL(
3996 15 : sqlite3_exec(hDB, osCommand, nullptr, nullptr, nullptr));
3997 :
3998 : osCommand.Printf("DROP TABLE 'idx_%s_%s_parent'",
3999 : pszEscapedLayerName,
4000 15 : SQLEscapeLiteral(pszGeometryColumn).c_str());
4001 15 : CPL_IGNORE_RET_VAL(
4002 15 : sqlite3_exec(hDB, osCommand, nullptr, nullptr, nullptr));
4003 :
4004 : osCommand.Printf("DROP TABLE 'idx_%s_%s_rowid'",
4005 : pszEscapedLayerName,
4006 15 : SQLEscapeLiteral(pszGeometryColumn).c_str());
4007 15 : CPL_IGNORE_RET_VAL(
4008 15 : sqlite3_exec(hDB, osCommand, nullptr, nullptr, nullptr));
4009 : }
4010 : }
4011 34 : return OGRERR_NONE;
4012 : }
4013 :
4014 : /************************************************************************/
4015 : /* StartTransaction() */
4016 : /* */
4017 : /* Should only be called by user code. Not driver internals. */
4018 : /************************************************************************/
4019 :
4020 317 : OGRErr OGRSQLiteBaseDataSource::StartTransaction(CPL_UNUSED int bForce)
4021 : {
4022 317 : if (m_bUserTransactionActive || m_nSoftTransactionLevel != 0)
4023 : {
4024 12 : CPLError(CE_Failure, CPLE_AppDefined,
4025 : "Transaction already established");
4026 12 : return OGRERR_FAILURE;
4027 : }
4028 :
4029 : // Check if we are in a SAVEPOINT transaction
4030 305 : if (m_aosSavepoints.size() > 0)
4031 : {
4032 0 : CPLError(CE_Failure, CPLE_AppDefined,
4033 : "Cannot start a transaction within a SAVEPOINT");
4034 0 : return OGRERR_FAILURE;
4035 : }
4036 :
4037 305 : OGRErr eErr = SoftStartTransaction();
4038 305 : if (eErr != OGRERR_NONE)
4039 0 : return eErr;
4040 :
4041 305 : m_bUserTransactionActive = true;
4042 305 : return OGRERR_NONE;
4043 : }
4044 :
4045 80 : OGRErr OGRSQLiteDataSource::StartTransaction(int bForce)
4046 : {
4047 151 : for (auto &poLayer : m_apoLayers)
4048 : {
4049 71 : if (poLayer->IsTableLayer())
4050 : {
4051 : OGRSQLiteTableLayer *poTableLayer =
4052 71 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
4053 71 : poTableLayer->RunDeferredCreationIfNecessary();
4054 : }
4055 : }
4056 :
4057 80 : return OGRSQLiteBaseDataSource::StartTransaction(bForce);
4058 : }
4059 :
4060 : /************************************************************************/
4061 : /* CommitTransaction() */
4062 : /* */
4063 : /* Should only be called by user code. Not driver internals. */
4064 : /************************************************************************/
4065 :
4066 265 : OGRErr OGRSQLiteBaseDataSource::CommitTransaction()
4067 : {
4068 265 : if (!m_bUserTransactionActive && !m_bImplicitTransactionOpened)
4069 : {
4070 3 : CPLError(CE_Failure, CPLE_AppDefined, "Transaction not established");
4071 3 : return OGRERR_FAILURE;
4072 : }
4073 :
4074 262 : m_bUserTransactionActive = false;
4075 262 : m_bImplicitTransactionOpened = false;
4076 262 : CPLAssert(m_nSoftTransactionLevel == 1);
4077 262 : return SoftCommitTransaction();
4078 : }
4079 :
4080 66 : OGRErr OGRSQLiteDataSource::CommitTransaction()
4081 :
4082 : {
4083 66 : if (m_nSoftTransactionLevel == 1)
4084 : {
4085 230 : for (auto &poLayer : m_apoLayers)
4086 : {
4087 166 : if (poLayer->IsTableLayer())
4088 : {
4089 : OGRSQLiteTableLayer *poTableLayer =
4090 166 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
4091 166 : poTableLayer->RunDeferredCreationIfNecessary();
4092 : }
4093 : }
4094 : }
4095 :
4096 66 : return OGRSQLiteBaseDataSource::CommitTransaction();
4097 : }
4098 :
4099 : /************************************************************************/
4100 : /* RollbackTransaction() */
4101 : /* */
4102 : /* Should only be called by user code. Not driver internals. */
4103 : /************************************************************************/
4104 :
4105 56 : OGRErr OGRSQLiteBaseDataSource::RollbackTransaction()
4106 : {
4107 56 : if (!m_bUserTransactionActive)
4108 : {
4109 3 : CPLError(CE_Failure, CPLE_AppDefined, "Transaction not established");
4110 3 : return OGRERR_FAILURE;
4111 : }
4112 :
4113 53 : m_bUserTransactionActive = false;
4114 53 : CPLAssert(m_nSoftTransactionLevel == 1);
4115 :
4116 53 : return SoftRollbackTransaction();
4117 : }
4118 :
4119 21 : OGRErr OGRSQLiteDataSource::RollbackTransaction()
4120 :
4121 : {
4122 21 : if (m_nSoftTransactionLevel == 1)
4123 : {
4124 38 : for (auto &poLayer : m_apoLayers)
4125 : {
4126 19 : if (poLayer->IsTableLayer())
4127 : {
4128 : OGRSQLiteTableLayer *poTableLayer =
4129 19 : cpl::down_cast<OGRSQLiteTableLayer *>(poLayer.get());
4130 19 : poTableLayer->RunDeferredCreationIfNecessary();
4131 : }
4132 : }
4133 :
4134 38 : for (auto &poLayer : m_apoLayers)
4135 : {
4136 19 : poLayer->InvalidateCachedFeatureCountAndExtent();
4137 19 : poLayer->ResetReading();
4138 : }
4139 : }
4140 :
4141 21 : return OGRSQLiteBaseDataSource::RollbackTransaction();
4142 : }
4143 :
4144 1695 : bool OGRSQLiteBaseDataSource::IsInTransaction() const
4145 : {
4146 1695 : return m_nSoftTransactionLevel > 0;
4147 : }
4148 :
4149 : /************************************************************************/
4150 : /* SoftStartTransaction() */
4151 : /* */
4152 : /* Create a transaction scope. If we already have a */
4153 : /* transaction active this isn't a real transaction, but just */
4154 : /* an increment to the scope count. */
4155 : /************************************************************************/
4156 :
4157 3339 : OGRErr OGRSQLiteBaseDataSource::SoftStartTransaction()
4158 :
4159 : {
4160 3339 : m_nSoftTransactionLevel++;
4161 :
4162 3339 : OGRErr eErr = OGRERR_NONE;
4163 3339 : if (m_nSoftTransactionLevel == 1)
4164 : {
4165 6429 : for (int i = 0; i < GetLayerCount(); i++)
4166 : {
4167 3278 : OGRLayer *poLayer = GetLayer(i);
4168 3278 : poLayer->PrepareStartTransaction();
4169 : }
4170 :
4171 3151 : eErr = DoTransactionCommand("BEGIN");
4172 : }
4173 :
4174 : // CPLDebug("SQLite", "%p->SoftStartTransaction() : %d",
4175 : // this, nSoftTransactionLevel);
4176 :
4177 3339 : return eErr;
4178 : }
4179 :
4180 : /************************************************************************/
4181 : /* SoftCommitTransaction() */
4182 : /* */
4183 : /* Commit the current transaction if we are at the outer */
4184 : /* scope. */
4185 : /************************************************************************/
4186 :
4187 3285 : OGRErr OGRSQLiteBaseDataSource::SoftCommitTransaction()
4188 :
4189 : {
4190 : // CPLDebug("SQLite", "%p->SoftCommitTransaction() : %d",
4191 : // this, nSoftTransactionLevel);
4192 :
4193 3285 : if (m_nSoftTransactionLevel <= 0)
4194 : {
4195 0 : CPLAssert(false);
4196 : return OGRERR_FAILURE;
4197 : }
4198 :
4199 3285 : OGRErr eErr = OGRERR_NONE;
4200 3285 : m_nSoftTransactionLevel--;
4201 3285 : if (m_nSoftTransactionLevel == 0)
4202 : {
4203 3097 : eErr = DoTransactionCommand("COMMIT");
4204 : }
4205 :
4206 3285 : return eErr;
4207 : }
4208 :
4209 : /************************************************************************/
4210 : /* SoftRollbackTransaction() */
4211 : /* */
4212 : /* Do a rollback of the current transaction if we are at the 1st */
4213 : /* level */
4214 : /************************************************************************/
4215 :
4216 124 : OGRErr OGRSQLiteBaseDataSource::SoftRollbackTransaction()
4217 :
4218 : {
4219 : // CPLDebug("SQLite", "%p->SoftRollbackTransaction() : %d",
4220 : // this, nSoftTransactionLevel);
4221 :
4222 124 : while (!m_aosSavepoints.empty())
4223 : {
4224 28 : if (RollbackToSavepoint(m_aosSavepoints.back()) != OGRERR_NONE)
4225 : {
4226 0 : return OGRERR_FAILURE;
4227 : }
4228 28 : m_aosSavepoints.pop_back();
4229 : }
4230 :
4231 96 : if (m_nSoftTransactionLevel <= 0)
4232 : {
4233 0 : CPLAssert(false);
4234 : return OGRERR_FAILURE;
4235 : }
4236 :
4237 96 : OGRErr eErr = OGRERR_NONE;
4238 96 : m_nSoftTransactionLevel--;
4239 96 : if (m_nSoftTransactionLevel == 0)
4240 : {
4241 96 : eErr = DoTransactionCommand("ROLLBACK");
4242 96 : if (eErr == OGRERR_NONE)
4243 : {
4244 186 : for (int i = 0; i < GetLayerCount(); i++)
4245 : {
4246 90 : OGRLayer *poLayer = GetLayer(i);
4247 90 : poLayer->FinishRollbackTransaction("");
4248 : }
4249 : }
4250 : }
4251 :
4252 96 : return eErr;
4253 : }
4254 :
4255 293 : OGRErr OGRSQLiteBaseDataSource::StartSavepoint(const std::string &osName)
4256 : {
4257 :
4258 : // A SAVEPOINT implicitly starts a transaction, let's fake one
4259 293 : if (!IsInTransaction())
4260 : {
4261 52 : m_bImplicitTransactionOpened = true;
4262 52 : m_nSoftTransactionLevel++;
4263 104 : for (int i = 0; i < GetLayerCount(); i++)
4264 : {
4265 52 : OGRLayer *poLayer = GetLayer(i);
4266 52 : poLayer->PrepareStartTransaction();
4267 : }
4268 : }
4269 :
4270 293 : const std::string osCommand = "SAVEPOINT " + osName;
4271 293 : const auto eErr = DoTransactionCommand(osCommand.c_str());
4272 :
4273 293 : if (eErr == OGRERR_NONE)
4274 : {
4275 293 : m_aosSavepoints.push_back(osName);
4276 : }
4277 :
4278 586 : return eErr;
4279 : }
4280 :
4281 32 : OGRErr OGRSQLiteBaseDataSource::ReleaseSavepoint(const std::string &osName)
4282 : {
4283 64 : if (m_aosSavepoints.empty() ||
4284 32 : std::find(m_aosSavepoints.cbegin(), m_aosSavepoints.cend(), osName) ==
4285 64 : m_aosSavepoints.cend())
4286 : {
4287 0 : CPLError(CE_Failure, CPLE_AppDefined, "Savepoint %s not found",
4288 : osName.c_str());
4289 0 : return OGRERR_FAILURE;
4290 : }
4291 :
4292 32 : const std::string osCommand = "RELEASE SAVEPOINT " + osName;
4293 32 : const auto eErr = DoTransactionCommand(osCommand.c_str());
4294 :
4295 32 : if (eErr == OGRERR_NONE)
4296 : {
4297 : // If the savepoint is the outer most, this is the same as COMMIT
4298 : // and the transaction is closed
4299 48 : if (m_bImplicitTransactionOpened &&
4300 16 : m_aosSavepoints.front().compare(osName) == 0)
4301 : {
4302 4 : m_bImplicitTransactionOpened = false;
4303 4 : m_bUserTransactionActive = false;
4304 4 : m_nSoftTransactionLevel = 0;
4305 4 : m_aosSavepoints.clear();
4306 : }
4307 : else
4308 : {
4309 : // Find all savepoints up to the target one and remove them
4310 64 : while (!m_aosSavepoints.empty() && m_aosSavepoints.back() != osName)
4311 : {
4312 36 : m_aosSavepoints.pop_back();
4313 : }
4314 28 : if (!m_aosSavepoints.empty()) // should always be true
4315 : {
4316 28 : m_aosSavepoints.pop_back();
4317 : }
4318 : }
4319 : }
4320 32 : return eErr;
4321 : }
4322 :
4323 117 : OGRErr OGRSQLiteBaseDataSource::RollbackToSavepoint(const std::string &osName)
4324 : {
4325 226 : if (m_aosSavepoints.empty() ||
4326 109 : std::find(m_aosSavepoints.cbegin(), m_aosSavepoints.cend(), osName) ==
4327 226 : m_aosSavepoints.cend())
4328 : {
4329 36 : CPLError(CE_Failure, CPLE_AppDefined, "Savepoint %s not found",
4330 : osName.c_str());
4331 36 : return OGRERR_FAILURE;
4332 : }
4333 :
4334 81 : const std::string osCommand = "ROLLBACK TO SAVEPOINT " + osName;
4335 81 : const auto eErr = DoTransactionCommand(osCommand.c_str());
4336 :
4337 81 : if (eErr == OGRERR_NONE)
4338 : {
4339 :
4340 : // The target savepoint should become the last one in the list
4341 : // and does not need to be removed because ROLLBACK TO SAVEPOINT
4342 137 : while (!m_aosSavepoints.empty() && m_aosSavepoints.back() != osName)
4343 : {
4344 56 : m_aosSavepoints.pop_back();
4345 : }
4346 : }
4347 :
4348 162 : for (int i = 0; i < GetLayerCount(); i++)
4349 : {
4350 81 : OGRLayer *poLayer = GetLayer(i);
4351 81 : poLayer->FinishRollbackTransaction(osName);
4352 : }
4353 :
4354 81 : return eErr;
4355 : }
4356 :
4357 : /************************************************************************/
4358 : /* ProcessTransactionSQL() */
4359 : /************************************************************************/
4360 7193 : bool OGRSQLiteBaseDataSource::ProcessTransactionSQL(
4361 : const std::string &osSQLCommand)
4362 : {
4363 7193 : bool retVal = true;
4364 :
4365 7193 : if (EQUAL(osSQLCommand.c_str(), "BEGIN"))
4366 : {
4367 60 : SoftStartTransaction();
4368 : }
4369 7133 : else if (EQUAL(osSQLCommand.c_str(), "COMMIT"))
4370 : {
4371 62 : SoftCommitTransaction();
4372 : }
4373 7071 : else if (EQUAL(osSQLCommand.c_str(), "ROLLBACK"))
4374 : {
4375 32 : SoftRollbackTransaction();
4376 : }
4377 7039 : else if (STARTS_WITH_CI(osSQLCommand.c_str(), "SAVEPOINT"))
4378 : {
4379 586 : const CPLStringList aosTokens(SQLTokenize(osSQLCommand.c_str()));
4380 293 : if (aosTokens.size() == 2)
4381 : {
4382 293 : const char *pszSavepointName = aosTokens[1];
4383 293 : StartSavepoint(pszSavepointName);
4384 : }
4385 : else
4386 : {
4387 0 : retVal = false;
4388 : }
4389 : }
4390 6746 : else if (STARTS_WITH_CI(osSQLCommand.c_str(), "RELEASE"))
4391 : {
4392 64 : const CPLStringList aosTokens(SQLTokenize(osSQLCommand.c_str()));
4393 32 : if (aosTokens.size() == 2)
4394 : {
4395 32 : const char *pszSavepointName = aosTokens[1];
4396 32 : ReleaseSavepoint(pszSavepointName);
4397 : }
4398 0 : else if (aosTokens.size() == 3 && EQUAL(aosTokens[1], "SAVEPOINT"))
4399 : {
4400 0 : const char *pszSavepointName = aosTokens[2];
4401 0 : ReleaseSavepoint(pszSavepointName);
4402 : }
4403 : else
4404 : {
4405 0 : retVal = false;
4406 : }
4407 : }
4408 6714 : else if (STARTS_WITH_CI(osSQLCommand.c_str(), "ROLLBACK"))
4409 : {
4410 178 : const CPLStringList aosTokens(SQLTokenize(osSQLCommand.c_str()));
4411 89 : if (aosTokens.size() == 2)
4412 : {
4413 56 : if (EQUAL(aosTokens[1], "TRANSACTION"))
4414 : {
4415 0 : SoftRollbackTransaction();
4416 : }
4417 : else
4418 : {
4419 56 : const char *pszSavepointName = aosTokens[1];
4420 56 : RollbackToSavepoint(pszSavepointName);
4421 : }
4422 : }
4423 33 : else if (aosTokens.size() > 1) // Savepoint name is last token
4424 : {
4425 33 : const char *pszSavepointName = aosTokens[aosTokens.size() - 1];
4426 33 : RollbackToSavepoint(pszSavepointName);
4427 : }
4428 : }
4429 : else
4430 : {
4431 6625 : retVal = false;
4432 : }
4433 :
4434 7193 : return retVal;
4435 : }
4436 :
4437 : /************************************************************************/
4438 : /* DoTransactionCommand() */
4439 : /************************************************************************/
4440 :
4441 6750 : OGRErr OGRSQLiteBaseDataSource::DoTransactionCommand(const char *pszCommand)
4442 :
4443 : {
4444 : #ifdef DEBUG
4445 6750 : CPLDebug("OGR_SQLITE", "%s Transaction", pszCommand);
4446 : #endif
4447 :
4448 6750 : return SQLCommand(hDB, pszCommand);
4449 : }
4450 :
4451 : /************************************************************************/
4452 : /* GetSRTEXTColName() */
4453 : /************************************************************************/
4454 :
4455 41 : const char *OGRSQLiteDataSource::GetSRTEXTColName()
4456 : {
4457 41 : if (!m_bIsSpatiaLiteDB || m_bSpatialite4Layout)
4458 26 : return "srtext";
4459 :
4460 : // Testing for SRS_WKT column presence.
4461 15 : bool bHasSrsWkt = false;
4462 15 : char **papszResult = nullptr;
4463 15 : int nRowCount = 0;
4464 15 : int nColCount = 0;
4465 15 : char *pszErrMsg = nullptr;
4466 : const int rc =
4467 15 : sqlite3_get_table(hDB, "PRAGMA table_info(spatial_ref_sys)",
4468 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
4469 :
4470 15 : if (rc == SQLITE_OK)
4471 : {
4472 98 : for (int iRow = 1; iRow <= nRowCount; iRow++)
4473 : {
4474 83 : if (EQUAL("srs_wkt", papszResult[(iRow * nColCount) + 1]))
4475 8 : bHasSrsWkt = true;
4476 : }
4477 15 : sqlite3_free_table(papszResult);
4478 : }
4479 : else
4480 : {
4481 0 : sqlite3_free(pszErrMsg);
4482 : }
4483 :
4484 15 : return bHasSrsWkt ? "srs_wkt" : nullptr;
4485 : }
4486 :
4487 : /************************************************************************/
4488 : /* AddSRIDToCache() */
4489 : /* */
4490 : /* Note: this will not add a reference on the poSRS object. Make */
4491 : /* sure it is freshly created, or add a reference yourself if not. */
4492 : /************************************************************************/
4493 :
4494 240 : OGRSpatialReference *OGRSQLiteDataSource::AddSRIDToCache(
4495 : int nId,
4496 : std::unique_ptr<OGRSpatialReference, OGRSpatialReferenceReleaser> &&poSRS)
4497 : {
4498 : /* -------------------------------------------------------------------- */
4499 : /* Add to the cache. */
4500 : /* -------------------------------------------------------------------- */
4501 240 : auto oIter = m_oSRSCache.emplace(nId, std::move(poSRS)).first;
4502 480 : return oIter->second.get();
4503 : }
4504 :
4505 : /************************************************************************/
4506 : /* FetchSRSId() */
4507 : /* */
4508 : /* Fetch the id corresponding to an SRS, and if not found, add */
4509 : /* it to the table. */
4510 : /************************************************************************/
4511 :
4512 257 : int OGRSQLiteDataSource::FetchSRSId(const OGRSpatialReference *poSRS)
4513 :
4514 : {
4515 257 : int nSRSId = m_nUndefinedSRID;
4516 257 : if (poSRS == nullptr)
4517 0 : return nSRSId;
4518 :
4519 : /* -------------------------------------------------------------------- */
4520 : /* First, we look through our SRID cache, is it there? */
4521 : /* -------------------------------------------------------------------- */
4522 452 : for (const auto &pair : m_oSRSCache)
4523 : {
4524 195 : if (pair.second.get() == poSRS)
4525 0 : return pair.first;
4526 : }
4527 357 : for (const auto &pair : m_oSRSCache)
4528 : {
4529 195 : if (pair.second != nullptr && pair.second->IsSame(poSRS))
4530 95 : return pair.first;
4531 : }
4532 :
4533 : /* -------------------------------------------------------------------- */
4534 : /* Build a copy since we may call AutoIdentifyEPSG() */
4535 : /* -------------------------------------------------------------------- */
4536 324 : OGRSpatialReference oSRS(*poSRS);
4537 162 : poSRS = nullptr;
4538 :
4539 162 : const char *pszAuthorityName = oSRS.GetAuthorityName(nullptr);
4540 162 : const char *pszAuthorityCode = nullptr;
4541 :
4542 162 : if (pszAuthorityName == nullptr || strlen(pszAuthorityName) == 0)
4543 : {
4544 : /* --------------------------------------------------------------------
4545 : */
4546 : /* Try to identify an EPSG code */
4547 : /* --------------------------------------------------------------------
4548 : */
4549 3 : oSRS.AutoIdentifyEPSG();
4550 :
4551 3 : pszAuthorityName = oSRS.GetAuthorityName(nullptr);
4552 3 : if (pszAuthorityName != nullptr && EQUAL(pszAuthorityName, "EPSG"))
4553 : {
4554 0 : pszAuthorityCode = oSRS.GetAuthorityCode(nullptr);
4555 0 : if (pszAuthorityCode != nullptr && strlen(pszAuthorityCode) > 0)
4556 : {
4557 : /* Import 'clean' SRS */
4558 0 : oSRS.importFromEPSG(atoi(pszAuthorityCode));
4559 :
4560 0 : pszAuthorityName = oSRS.GetAuthorityName(nullptr);
4561 0 : pszAuthorityCode = oSRS.GetAuthorityCode(nullptr);
4562 : }
4563 : }
4564 : }
4565 :
4566 : /* -------------------------------------------------------------------- */
4567 : /* Check whether the EPSG authority code is already mapped to a */
4568 : /* SRS ID. */
4569 : /* -------------------------------------------------------------------- */
4570 162 : char *pszErrMsg = nullptr;
4571 324 : CPLString osCommand;
4572 162 : char **papszResult = nullptr;
4573 162 : int nRowCount = 0;
4574 162 : int nColCount = 0;
4575 :
4576 162 : if (pszAuthorityName != nullptr && strlen(pszAuthorityName) > 0)
4577 : {
4578 159 : pszAuthorityCode = oSRS.GetAuthorityCode(nullptr);
4579 :
4580 159 : if (pszAuthorityCode != nullptr && strlen(pszAuthorityCode) > 0)
4581 : {
4582 : // XXX: We are using case insensitive comparison for "auth_name"
4583 : // values, because there are variety of options exist. By default
4584 : // the driver uses 'EPSG' in upper case, but SpatiaLite extension
4585 : // uses 'epsg' in lower case.
4586 : osCommand.Printf(
4587 : "SELECT srid FROM spatial_ref_sys WHERE "
4588 : "auth_name = '%s' COLLATE NOCASE AND auth_srid = '%s' "
4589 : "LIMIT 2",
4590 159 : pszAuthorityName, pszAuthorityCode);
4591 :
4592 159 : int rc = sqlite3_get_table(hDB, osCommand, &papszResult, &nRowCount,
4593 : &nColCount, &pszErrMsg);
4594 159 : if (rc != SQLITE_OK)
4595 : {
4596 : /* Retry without COLLATE NOCASE which may not be understood by
4597 : * older sqlite3 */
4598 0 : sqlite3_free(pszErrMsg);
4599 :
4600 : osCommand.Printf("SELECT srid FROM spatial_ref_sys WHERE "
4601 : "auth_name = '%s' AND auth_srid = '%s'",
4602 0 : pszAuthorityName, pszAuthorityCode);
4603 :
4604 0 : rc = sqlite3_get_table(hDB, osCommand, &papszResult, &nRowCount,
4605 : &nColCount, &pszErrMsg);
4606 :
4607 : /* Retry in lower case for SpatiaLite */
4608 0 : if (rc != SQLITE_OK)
4609 : {
4610 0 : sqlite3_free(pszErrMsg);
4611 : }
4612 0 : else if (nRowCount == 0 &&
4613 0 : strcmp(pszAuthorityName, "EPSG") == 0)
4614 : {
4615 : /* If it is in upper case, look for lower case */
4616 0 : sqlite3_free_table(papszResult);
4617 :
4618 : osCommand.Printf("SELECT srid FROM spatial_ref_sys WHERE "
4619 : "auth_name = 'epsg' AND auth_srid = '%s' "
4620 : "LIMIT 2",
4621 0 : pszAuthorityCode);
4622 :
4623 0 : rc = sqlite3_get_table(hDB, osCommand, &papszResult,
4624 : &nRowCount, &nColCount, &pszErrMsg);
4625 :
4626 0 : if (rc != SQLITE_OK)
4627 : {
4628 0 : sqlite3_free(pszErrMsg);
4629 : }
4630 : }
4631 : }
4632 :
4633 159 : if (rc == SQLITE_OK && nRowCount == 1)
4634 : {
4635 136 : nSRSId = (papszResult[1] != nullptr) ? atoi(papszResult[1])
4636 : : m_nUndefinedSRID;
4637 136 : sqlite3_free_table(papszResult);
4638 :
4639 136 : if (nSRSId != m_nUndefinedSRID)
4640 : {
4641 : std::unique_ptr<OGRSpatialReference,
4642 : OGRSpatialReferenceReleaser>
4643 272 : poCachedSRS(new OGRSpatialReference(oSRS));
4644 136 : poCachedSRS->SetAxisMappingStrategy(
4645 : OAMS_TRADITIONAL_GIS_ORDER);
4646 136 : AddSRIDToCache(nSRSId, std::move(poCachedSRS));
4647 : }
4648 :
4649 136 : return nSRSId;
4650 : }
4651 23 : sqlite3_free_table(papszResult);
4652 : }
4653 : }
4654 :
4655 : /* -------------------------------------------------------------------- */
4656 : /* Search for existing record using either WKT definition or */
4657 : /* PROJ.4 string (SpatiaLite variant). */
4658 : /* -------------------------------------------------------------------- */
4659 52 : CPLString osWKT;
4660 52 : CPLString osProj4;
4661 :
4662 : /* -------------------------------------------------------------------- */
4663 : /* Translate SRS to WKT. */
4664 : /* -------------------------------------------------------------------- */
4665 26 : char *pszWKT = nullptr;
4666 :
4667 26 : if (oSRS.exportToWkt(&pszWKT) != OGRERR_NONE)
4668 : {
4669 0 : CPLFree(pszWKT);
4670 0 : return m_nUndefinedSRID;
4671 : }
4672 :
4673 26 : osWKT = pszWKT;
4674 26 : CPLFree(pszWKT);
4675 26 : pszWKT = nullptr;
4676 :
4677 26 : const char *pszSRTEXTColName = GetSRTEXTColName();
4678 :
4679 26 : if (pszSRTEXTColName != nullptr)
4680 : {
4681 : /* --------------------------------------------------------------------
4682 : */
4683 : /* Try to find based on the WKT match. */
4684 : /* --------------------------------------------------------------------
4685 : */
4686 : osCommand.Printf("SELECT srid FROM spatial_ref_sys WHERE \"%s\" = ? "
4687 : "LIMIT 2",
4688 26 : SQLEscapeName(pszSRTEXTColName).c_str());
4689 : }
4690 :
4691 : /* -------------------------------------------------------------------- */
4692 : /* Handle SpatiaLite (< 4) flavor of the spatial_ref_sys. */
4693 : /* -------------------------------------------------------------------- */
4694 : else
4695 : {
4696 : /* --------------------------------------------------------------------
4697 : */
4698 : /* Translate SRS to PROJ.4 string. */
4699 : /* --------------------------------------------------------------------
4700 : */
4701 0 : char *pszProj4 = nullptr;
4702 :
4703 0 : if (oSRS.exportToProj4(&pszProj4) != OGRERR_NONE)
4704 : {
4705 0 : CPLFree(pszProj4);
4706 0 : return m_nUndefinedSRID;
4707 : }
4708 :
4709 0 : osProj4 = pszProj4;
4710 0 : CPLFree(pszProj4);
4711 0 : pszProj4 = nullptr;
4712 :
4713 : /* --------------------------------------------------------------------
4714 : */
4715 : /* Try to find based on the PROJ.4 match. */
4716 : /* --------------------------------------------------------------------
4717 : */
4718 : osCommand.Printf(
4719 0 : "SELECT srid FROM spatial_ref_sys WHERE proj4text = ? LIMIT 2");
4720 : }
4721 :
4722 26 : sqlite3_stmt *hSelectStmt = nullptr;
4723 26 : int rc = prepareSql(hDB, osCommand, -1, &hSelectStmt, nullptr);
4724 :
4725 26 : if (rc == SQLITE_OK)
4726 52 : rc = sqlite3_bind_text(hSelectStmt, 1,
4727 26 : (pszSRTEXTColName != nullptr) ? osWKT.c_str()
4728 0 : : osProj4.c_str(),
4729 : -1, SQLITE_STATIC);
4730 :
4731 26 : if (rc == SQLITE_OK)
4732 26 : rc = sqlite3_step(hSelectStmt);
4733 :
4734 26 : if (rc == SQLITE_ROW)
4735 : {
4736 0 : if (sqlite3_column_type(hSelectStmt, 0) == SQLITE_INTEGER)
4737 0 : nSRSId = sqlite3_column_int(hSelectStmt, 0);
4738 : else
4739 0 : nSRSId = m_nUndefinedSRID;
4740 :
4741 0 : sqlite3_finalize(hSelectStmt);
4742 :
4743 0 : if (nSRSId != m_nUndefinedSRID)
4744 : {
4745 : auto poSRSClone = std::unique_ptr<OGRSpatialReference,
4746 : OGRSpatialReferenceReleaser>(
4747 0 : new OGRSpatialReference(oSRS));
4748 0 : AddSRIDToCache(nSRSId, std::move(poSRSClone));
4749 : }
4750 :
4751 0 : return nSRSId;
4752 : }
4753 :
4754 : /* -------------------------------------------------------------------- */
4755 : /* If the command actually failed, then the metadata table is */
4756 : /* likely missing, so we give up. */
4757 : /* -------------------------------------------------------------------- */
4758 26 : if (rc != SQLITE_DONE && rc != SQLITE_ROW)
4759 : {
4760 0 : sqlite3_finalize(hSelectStmt);
4761 0 : return m_nUndefinedSRID;
4762 : }
4763 :
4764 26 : sqlite3_finalize(hSelectStmt);
4765 :
4766 : /* -------------------------------------------------------------------- */
4767 : /* Translate SRS to PROJ.4 string (if not already done) */
4768 : /* -------------------------------------------------------------------- */
4769 26 : if (osProj4.empty())
4770 : {
4771 26 : char *pszProj4 = nullptr;
4772 26 : if (oSRS.exportToProj4(&pszProj4) == OGRERR_NONE)
4773 : {
4774 24 : osProj4 = pszProj4;
4775 : }
4776 26 : CPLFree(pszProj4);
4777 26 : pszProj4 = nullptr;
4778 : }
4779 :
4780 : /* -------------------------------------------------------------------- */
4781 : /* If we have an authority code try to assign SRS ID the same */
4782 : /* as that code. */
4783 : /* -------------------------------------------------------------------- */
4784 26 : if (pszAuthorityCode != nullptr && strlen(pszAuthorityCode) > 0)
4785 : {
4786 : osCommand.Printf("SELECT * FROM spatial_ref_sys WHERE auth_srid='%s' "
4787 : "LIMIT 2",
4788 23 : SQLEscapeLiteral(pszAuthorityCode).c_str());
4789 23 : rc = sqlite3_get_table(hDB, osCommand, &papszResult, &nRowCount,
4790 : &nColCount, &pszErrMsg);
4791 :
4792 23 : if (rc != SQLITE_OK)
4793 : {
4794 0 : CPLError(CE_Failure, CPLE_AppDefined,
4795 : "exec(SELECT '%s' FROM spatial_ref_sys) failed: %s",
4796 : pszAuthorityCode, pszErrMsg);
4797 0 : sqlite3_free(pszErrMsg);
4798 : }
4799 :
4800 : /* --------------------------------------------------------------------
4801 : */
4802 : /* If there is no SRS ID with such auth_srid, use it as SRS ID. */
4803 : /* --------------------------------------------------------------------
4804 : */
4805 23 : if (nRowCount < 1)
4806 : {
4807 23 : nSRSId = atoi(pszAuthorityCode);
4808 : /* The authority code might be non numeric, e.g. IGNF:LAMB93 */
4809 : /* in which case we might fallback to the fake OGR authority */
4810 : /* for spatialite, since its auth_srid is INTEGER */
4811 23 : if (nSRSId == 0)
4812 : {
4813 0 : nSRSId = m_nUndefinedSRID;
4814 0 : if (m_bIsSpatiaLiteDB)
4815 0 : pszAuthorityName = nullptr;
4816 : }
4817 : }
4818 23 : sqlite3_free_table(papszResult);
4819 : }
4820 :
4821 : /* -------------------------------------------------------------------- */
4822 : /* Otherwise get the current maximum srid in the srs table. */
4823 : /* -------------------------------------------------------------------- */
4824 26 : if (nSRSId == m_nUndefinedSRID)
4825 : {
4826 : rc =
4827 3 : sqlite3_get_table(hDB, "SELECT MAX(srid) FROM spatial_ref_sys",
4828 : &papszResult, &nRowCount, &nColCount, &pszErrMsg);
4829 :
4830 3 : if (rc != SQLITE_OK)
4831 : {
4832 0 : CPLError(CE_Failure, CPLE_AppDefined,
4833 : "SELECT of the maximum SRS ID failed: %s", pszErrMsg);
4834 0 : sqlite3_free(pszErrMsg);
4835 0 : return m_nUndefinedSRID;
4836 : }
4837 :
4838 3 : if (nRowCount < 1 || !papszResult[1])
4839 1 : nSRSId = 50000;
4840 : else
4841 2 : nSRSId = atoi(papszResult[1]) + 1; // Insert as the next SRS ID
4842 3 : sqlite3_free_table(papszResult);
4843 : }
4844 :
4845 : /* -------------------------------------------------------------------- */
4846 : /* Try adding the SRS to the SRS table. */
4847 : /* -------------------------------------------------------------------- */
4848 :
4849 26 : const char *apszToInsert[] = {nullptr, nullptr, nullptr,
4850 : nullptr, nullptr, nullptr};
4851 :
4852 26 : if (!m_bIsSpatiaLiteDB)
4853 : {
4854 23 : if (pszAuthorityName != nullptr)
4855 : {
4856 : osCommand.Printf(
4857 : "INSERT INTO spatial_ref_sys (srid,srtext,auth_name,auth_srid) "
4858 : " VALUES (%d, ?, ?, ?)",
4859 22 : nSRSId);
4860 22 : apszToInsert[0] = osWKT.c_str();
4861 22 : apszToInsert[1] = pszAuthorityName;
4862 22 : apszToInsert[2] = pszAuthorityCode;
4863 : }
4864 : else
4865 : {
4866 : osCommand.Printf("INSERT INTO spatial_ref_sys (srid,srtext) "
4867 : " VALUES (%d, ?)",
4868 1 : nSRSId);
4869 1 : apszToInsert[0] = osWKT.c_str();
4870 : }
4871 : }
4872 : else
4873 : {
4874 6 : CPLString osSRTEXTColNameWithCommaBefore;
4875 3 : if (pszSRTEXTColName != nullptr)
4876 3 : osSRTEXTColNameWithCommaBefore.Printf(", %s", pszSRTEXTColName);
4877 :
4878 3 : const char *pszProjCS = oSRS.GetAttrValue("PROJCS");
4879 3 : if (pszProjCS == nullptr)
4880 1 : pszProjCS = oSRS.GetAttrValue("GEOGCS");
4881 :
4882 3 : if (pszAuthorityName != nullptr)
4883 : {
4884 1 : if (pszProjCS)
4885 : {
4886 : osCommand.Printf(
4887 : "INSERT INTO spatial_ref_sys "
4888 : "(srid, auth_name, auth_srid, ref_sys_name, proj4text%s) "
4889 : "VALUES (%d, ?, ?, ?, ?%s)",
4890 : (pszSRTEXTColName != nullptr)
4891 1 : ? osSRTEXTColNameWithCommaBefore.c_str()
4892 : : "",
4893 2 : nSRSId, (pszSRTEXTColName != nullptr) ? ", ?" : "");
4894 1 : apszToInsert[0] = pszAuthorityName;
4895 1 : apszToInsert[1] = pszAuthorityCode;
4896 1 : apszToInsert[2] = pszProjCS;
4897 1 : apszToInsert[3] = osProj4.c_str();
4898 1 : apszToInsert[4] =
4899 1 : (pszSRTEXTColName != nullptr) ? osWKT.c_str() : nullptr;
4900 : }
4901 : else
4902 : {
4903 : osCommand.Printf("INSERT INTO spatial_ref_sys "
4904 : "(srid, auth_name, auth_srid, proj4text%s) "
4905 : "VALUES (%d, ?, ?, ?%s)",
4906 : (pszSRTEXTColName != nullptr)
4907 0 : ? osSRTEXTColNameWithCommaBefore.c_str()
4908 : : "",
4909 : nSRSId,
4910 0 : (pszSRTEXTColName != nullptr) ? ", ?" : "");
4911 0 : apszToInsert[0] = pszAuthorityName;
4912 0 : apszToInsert[1] = pszAuthorityCode;
4913 0 : apszToInsert[2] = osProj4.c_str();
4914 0 : apszToInsert[3] =
4915 0 : (pszSRTEXTColName != nullptr) ? osWKT.c_str() : nullptr;
4916 : }
4917 : }
4918 : else
4919 : {
4920 : /* SpatiaLite spatial_ref_sys auth_name and auth_srid columns must
4921 : * be NOT NULL */
4922 : /* so insert within a fake OGR "authority" */
4923 2 : if (pszProjCS)
4924 : {
4925 : osCommand.Printf("INSERT INTO spatial_ref_sys "
4926 : "(srid, auth_name, auth_srid, ref_sys_name, "
4927 : "proj4text%s) VALUES (%d, 'OGR', %d, ?, ?%s)",
4928 : (pszSRTEXTColName != nullptr)
4929 1 : ? osSRTEXTColNameWithCommaBefore.c_str()
4930 : : "",
4931 : nSRSId, nSRSId,
4932 2 : (pszSRTEXTColName != nullptr) ? ", ?" : "");
4933 1 : apszToInsert[0] = pszProjCS;
4934 1 : apszToInsert[1] = osProj4.c_str();
4935 1 : apszToInsert[2] =
4936 1 : (pszSRTEXTColName != nullptr) ? osWKT.c_str() : nullptr;
4937 : }
4938 : else
4939 : {
4940 : osCommand.Printf("INSERT INTO spatial_ref_sys "
4941 : "(srid, auth_name, auth_srid, proj4text%s) "
4942 : "VALUES (%d, 'OGR', %d, ?%s)",
4943 : (pszSRTEXTColName != nullptr)
4944 1 : ? osSRTEXTColNameWithCommaBefore.c_str()
4945 : : "",
4946 : nSRSId, nSRSId,
4947 2 : (pszSRTEXTColName != nullptr) ? ", ?" : "");
4948 1 : apszToInsert[0] = osProj4.c_str();
4949 1 : apszToInsert[1] =
4950 1 : (pszSRTEXTColName != nullptr) ? osWKT.c_str() : nullptr;
4951 : }
4952 : }
4953 : }
4954 :
4955 26 : sqlite3_stmt *hInsertStmt = nullptr;
4956 26 : rc = prepareSql(hDB, osCommand, -1, &hInsertStmt, nullptr);
4957 :
4958 103 : for (int i = 0; apszToInsert[i] != nullptr; i++)
4959 : {
4960 77 : if (rc == SQLITE_OK)
4961 77 : rc = sqlite3_bind_text(hInsertStmt, i + 1, apszToInsert[i], -1,
4962 : SQLITE_STATIC);
4963 : }
4964 :
4965 26 : if (rc == SQLITE_OK)
4966 26 : rc = sqlite3_step(hInsertStmt);
4967 :
4968 26 : if (rc != SQLITE_OK && rc != SQLITE_DONE)
4969 : {
4970 0 : CPLError(CE_Failure, CPLE_AppDefined, "Unable to insert SRID (%s): %s",
4971 : osCommand.c_str(), sqlite3_errmsg(hDB));
4972 :
4973 0 : sqlite3_finalize(hInsertStmt);
4974 0 : return FALSE;
4975 : }
4976 :
4977 26 : sqlite3_finalize(hInsertStmt);
4978 :
4979 26 : if (nSRSId != m_nUndefinedSRID)
4980 : {
4981 : std::unique_ptr<OGRSpatialReference, OGRSpatialReferenceReleaser>
4982 52 : poCachedSRS(new OGRSpatialReference(std::move(oSRS)));
4983 26 : poCachedSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
4984 26 : AddSRIDToCache(nSRSId, std::move(poCachedSRS));
4985 : }
4986 :
4987 26 : return nSRSId;
4988 : }
4989 :
4990 : /************************************************************************/
4991 : /* FetchSRS() */
4992 : /* */
4993 : /* Return a SRS corresponding to a particular id. Note that */
4994 : /* reference counting should be honoured on the returned */
4995 : /* OGRSpatialReference, as handles may be cached. */
4996 : /************************************************************************/
4997 :
4998 661 : OGRSpatialReference *OGRSQLiteDataSource::FetchSRS(int nId)
4999 :
5000 : {
5001 661 : if (nId <= 0)
5002 389 : return nullptr;
5003 :
5004 : /* -------------------------------------------------------------------- */
5005 : /* First, we look through our SRID cache, is it there? */
5006 : /* -------------------------------------------------------------------- */
5007 272 : const auto oIter = m_oSRSCache.find(nId);
5008 272 : if (oIter != m_oSRSCache.end())
5009 : {
5010 185 : return oIter->second.get();
5011 : }
5012 :
5013 : /* -------------------------------------------------------------------- */
5014 : /* Try looking up in spatial_ref_sys table. */
5015 : /* -------------------------------------------------------------------- */
5016 87 : char *pszErrMsg = nullptr;
5017 87 : char **papszResult = nullptr;
5018 87 : int nRowCount = 0;
5019 87 : int nColCount = 0;
5020 87 : std::unique_ptr<OGRSpatialReference, OGRSpatialReferenceReleaser> poSRS;
5021 :
5022 174 : CPLString osCommand;
5023 87 : osCommand.Printf("SELECT srtext FROM spatial_ref_sys WHERE srid = %d "
5024 : "LIMIT 2",
5025 87 : nId);
5026 87 : int rc = sqlite3_get_table(hDB, osCommand, &papszResult, &nRowCount,
5027 : &nColCount, &pszErrMsg);
5028 :
5029 87 : if (rc == SQLITE_OK)
5030 : {
5031 72 : if (nRowCount < 1)
5032 : {
5033 2 : sqlite3_free_table(papszResult);
5034 2 : return nullptr;
5035 : }
5036 :
5037 70 : char **papszRow = papszResult + nColCount;
5038 70 : if (papszRow[0] != nullptr)
5039 : {
5040 140 : CPLString osWKT = papszRow[0];
5041 :
5042 : /* --------------------------------------------------------------------
5043 : */
5044 : /* Translate into a spatial reference. */
5045 : /* --------------------------------------------------------------------
5046 : */
5047 70 : poSRS.reset(new OGRSpatialReference());
5048 70 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5049 70 : if (poSRS->importFromWkt(osWKT.c_str()) != OGRERR_NONE)
5050 : {
5051 2 : poSRS.reset();
5052 : }
5053 : }
5054 :
5055 70 : sqlite3_free_table(papszResult);
5056 : }
5057 :
5058 : /* -------------------------------------------------------------------- */
5059 : /* Next try SpatiaLite flavor. SpatiaLite uses PROJ.4 strings */
5060 : /* in 'proj4text' column instead of WKT in 'srtext'. Note: recent */
5061 : /* versions of spatialite have a srs_wkt column too */
5062 : /* -------------------------------------------------------------------- */
5063 : else
5064 : {
5065 15 : sqlite3_free(pszErrMsg);
5066 15 : pszErrMsg = nullptr;
5067 :
5068 15 : const char *pszSRTEXTColName = GetSRTEXTColName();
5069 15 : CPLString osSRTEXTColNameWithCommaBefore;
5070 15 : if (pszSRTEXTColName != nullptr)
5071 8 : osSRTEXTColNameWithCommaBefore.Printf(", %s", pszSRTEXTColName);
5072 :
5073 15 : osCommand.Printf(
5074 : "SELECT proj4text, auth_name, auth_srid%s FROM spatial_ref_sys "
5075 : "WHERE srid = %d LIMIT 2",
5076 : (pszSRTEXTColName != nullptr)
5077 8 : ? osSRTEXTColNameWithCommaBefore.c_str()
5078 : : "",
5079 23 : nId);
5080 15 : rc = sqlite3_get_table(hDB, osCommand, &papszResult, &nRowCount,
5081 : &nColCount, &pszErrMsg);
5082 15 : if (rc == SQLITE_OK)
5083 : {
5084 15 : if (nRowCount < 1)
5085 : {
5086 7 : sqlite3_free_table(papszResult);
5087 7 : return nullptr;
5088 : }
5089 :
5090 : /* --------------------------------------------------------------------
5091 : */
5092 : /* Translate into a spatial reference. */
5093 : /* --------------------------------------------------------------------
5094 : */
5095 8 : char **papszRow = papszResult + nColCount;
5096 :
5097 8 : const char *pszProj4Text = papszRow[0];
5098 8 : const char *pszAuthName = papszRow[1];
5099 8 : int nAuthSRID = (papszRow[2] != nullptr) ? atoi(papszRow[2]) : 0;
5100 8 : const char *pszWKT =
5101 8 : (pszSRTEXTColName != nullptr) ? papszRow[3] : nullptr;
5102 :
5103 8 : poSRS.reset(new OGRSpatialReference());
5104 8 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
5105 :
5106 : /* Try first from EPSG code */
5107 16 : if (pszAuthName != nullptr && EQUAL(pszAuthName, "EPSG") &&
5108 8 : poSRS->importFromEPSG(nAuthSRID) == OGRERR_NONE)
5109 : {
5110 : /* Do nothing */
5111 : }
5112 : /* Then from WKT string */
5113 0 : else if (pszWKT != nullptr &&
5114 0 : poSRS->importFromWkt(pszWKT) == OGRERR_NONE)
5115 : {
5116 : /* Do nothing */
5117 : }
5118 : /* Finally from Proj4 string */
5119 0 : else if (pszProj4Text != nullptr &&
5120 0 : poSRS->importFromProj4(pszProj4Text) == OGRERR_NONE)
5121 : {
5122 : /* Do nothing */
5123 : }
5124 : else
5125 : {
5126 0 : poSRS.reset();
5127 : }
5128 :
5129 8 : sqlite3_free_table(papszResult);
5130 : }
5131 :
5132 : /* --------------------------------------------------------------------
5133 : */
5134 : /* No success, report an error. */
5135 : /* --------------------------------------------------------------------
5136 : */
5137 : else
5138 : {
5139 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s: %s", osCommand.c_str(),
5140 : pszErrMsg);
5141 0 : sqlite3_free(pszErrMsg);
5142 0 : return nullptr;
5143 : }
5144 : }
5145 :
5146 78 : if (poSRS)
5147 76 : poSRS->StripTOWGS84IfKnownDatumAndAllowed();
5148 :
5149 : /* -------------------------------------------------------------------- */
5150 : /* Add to the cache. */
5151 : /* -------------------------------------------------------------------- */
5152 78 : return AddSRIDToCache(nId, std::move(poSRS));
5153 : }
5154 :
5155 : /************************************************************************/
5156 : /* SetName() */
5157 : /************************************************************************/
5158 :
5159 0 : void OGRSQLiteDataSource::SetName(const char *pszNameIn)
5160 : {
5161 0 : CPLFree(m_pszFilename);
5162 0 : m_pszFilename = CPLStrdup(pszNameIn);
5163 0 : }
5164 :
5165 : /************************************************************************/
5166 : /* GetEnvelopeFromSQL() */
5167 : /************************************************************************/
5168 :
5169 : const OGREnvelope *
5170 16 : OGRSQLiteBaseDataSource::GetEnvelopeFromSQL(const CPLString &osSQL)
5171 : {
5172 16 : const auto oIter = oMapSQLEnvelope.find(osSQL);
5173 16 : if (oIter != oMapSQLEnvelope.end())
5174 5 : return &oIter->second;
5175 : else
5176 11 : return nullptr;
5177 : }
5178 :
5179 : /************************************************************************/
5180 : /* SetEnvelopeForSQL() */
5181 : /************************************************************************/
5182 :
5183 5 : void OGRSQLiteBaseDataSource::SetEnvelopeForSQL(const CPLString &osSQL,
5184 : const OGREnvelope &oEnvelope)
5185 : {
5186 5 : oMapSQLEnvelope[osSQL] = oEnvelope;
5187 5 : }
5188 :
5189 : /***********************************************************************/
5190 : /* SetQueryLoggerFunc() */
5191 : /***********************************************************************/
5192 :
5193 1 : bool OGRSQLiteBaseDataSource::SetQueryLoggerFunc(
5194 : GDALQueryLoggerFunc pfnQueryLoggerFuncIn, void *poQueryLoggerArgIn)
5195 : {
5196 1 : pfnQueryLoggerFunc = pfnQueryLoggerFuncIn;
5197 1 : poQueryLoggerArg = poQueryLoggerArgIn;
5198 :
5199 1 : if (pfnQueryLoggerFunc)
5200 : {
5201 1 : sqlite3_trace_v2(
5202 : hDB, SQLITE_TRACE_PROFILE,
5203 17 : [](unsigned int /* traceProfile */, void *context,
5204 : void *preparedStatement, void *executionTime) -> int
5205 : {
5206 17 : if (context)
5207 : {
5208 17 : char *pzsSql{sqlite3_expanded_sql(
5209 : reinterpret_cast<sqlite3_stmt *>(preparedStatement))};
5210 17 : if (pzsSql)
5211 : {
5212 34 : const std::string sql{pzsSql};
5213 17 : sqlite3_free(pzsSql);
5214 17 : const uint64_t executionTimeMilliSeconds{
5215 : static_cast<uint64_t>(
5216 17 : *reinterpret_cast<uint64_t *>(executionTime) /
5217 : 1e+6)};
5218 17 : OGRSQLiteBaseDataSource *source{
5219 : reinterpret_cast<OGRSQLiteBaseDataSource *>(
5220 : context)};
5221 17 : if (source->pfnQueryLoggerFunc)
5222 : {
5223 17 : source->pfnQueryLoggerFunc(
5224 : sql.c_str(), nullptr, -1,
5225 : executionTimeMilliSeconds,
5226 : source->poQueryLoggerArg);
5227 : }
5228 : }
5229 : }
5230 17 : return 0;
5231 : },
5232 : reinterpret_cast<void *>(this));
5233 1 : return true;
5234 : }
5235 0 : return false;
5236 : }
5237 :
5238 : /************************************************************************/
5239 : /* AbortSQL() */
5240 : /************************************************************************/
5241 :
5242 2 : OGRErr OGRSQLiteBaseDataSource::AbortSQL()
5243 : {
5244 2 : sqlite3_interrupt(hDB);
5245 2 : return OGRERR_NONE;
5246 : }
|