Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Run SQL requests with SQLite SQL engine
5 : * Author: Even Rouault, even dot rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2012-2013, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "ogr_sqlite.h"
14 : #include "ogrsqliteexecutesql.h"
15 : #include "ogrsqlitevirtualogr.h"
16 : #include "ogrsqliteutility.h"
17 :
18 : #include <cctype>
19 : #include <cstdio>
20 : #include <cstring>
21 :
22 : #include "cpl_conv.h"
23 : #include "cpl_error.h"
24 : #include "cpl_multiproc.h"
25 : #include "cpl_port.h"
26 : #include "cpl_string.h"
27 : #include "cpl_vsi.h"
28 : #include "gdal_priv.h"
29 : #include "ogr_api.h"
30 : #include "ogr_core.h"
31 : #include "ogr_feature.h"
32 : #include "ogr_geometry.h"
33 : #include "ogr_spatialref.h"
34 : #include "sqlite3.h"
35 :
36 : /************************************************************************/
37 : /* OGR2SQLITEExtractUnquotedString() */
38 : /************************************************************************/
39 :
40 389 : static CPLString OGR2SQLITEExtractUnquotedString(const char **ppszSQLCommand)
41 : {
42 389 : CPLString osRet;
43 389 : const char *pszSQLCommand = *ppszSQLCommand;
44 389 : if (*pszSQLCommand == '"' || *pszSQLCommand == '\'')
45 : {
46 19 : const char chQuoteChar = *pszSQLCommand;
47 19 : pszSQLCommand++;
48 :
49 193 : while (*pszSQLCommand != '\0')
50 : {
51 193 : if (*pszSQLCommand == chQuoteChar &&
52 19 : pszSQLCommand[1] == chQuoteChar)
53 : {
54 0 : pszSQLCommand++;
55 0 : osRet += chQuoteChar;
56 : }
57 193 : else if (*pszSQLCommand == chQuoteChar)
58 : {
59 19 : pszSQLCommand++;
60 19 : break;
61 : }
62 : else
63 174 : osRet += *pszSQLCommand;
64 :
65 174 : pszSQLCommand++;
66 19 : }
67 : }
68 : else
69 : {
70 370 : bool bNotATableName = false;
71 370 : char chQuoteChar = 0;
72 370 : int nParenthesisLevel = 0;
73 2974 : while (*pszSQLCommand != '\0')
74 : {
75 2932 : if (*pszSQLCommand == chQuoteChar &&
76 0 : pszSQLCommand[1] == chQuoteChar)
77 : {
78 0 : osRet += *pszSQLCommand;
79 0 : pszSQLCommand++;
80 : }
81 2932 : else if (*pszSQLCommand == chQuoteChar)
82 : {
83 0 : chQuoteChar = 0;
84 : }
85 2932 : else if (chQuoteChar == 0)
86 : {
87 2932 : if (*pszSQLCommand == '(')
88 : {
89 2 : bNotATableName = true;
90 2 : nParenthesisLevel++;
91 : }
92 2930 : else if (*pszSQLCommand == ')')
93 : {
94 6 : nParenthesisLevel--;
95 6 : if (nParenthesisLevel < 0)
96 4 : break;
97 : }
98 2924 : else if (*pszSQLCommand == '"' || *pszSQLCommand == '\'')
99 : {
100 0 : chQuoteChar = *pszSQLCommand;
101 : }
102 2924 : else if (nParenthesisLevel == 0 &&
103 2908 : (isspace(static_cast<unsigned char>(*pszSQLCommand)) ||
104 2588 : *pszSQLCommand == '.' || *pszSQLCommand == ','))
105 : {
106 : break;
107 : }
108 : }
109 :
110 2604 : osRet += *pszSQLCommand;
111 2604 : pszSQLCommand++;
112 : }
113 370 : if (bNotATableName)
114 2 : osRet.clear();
115 : }
116 :
117 389 : *ppszSQLCommand = pszSQLCommand;
118 :
119 389 : return osRet;
120 : }
121 :
122 : /************************************************************************/
123 : /* OGR2SQLITEExtractLayerDesc() */
124 : /************************************************************************/
125 :
126 374 : static LayerDesc OGR2SQLITEExtractLayerDesc(const char **ppszSQLCommand)
127 : {
128 748 : std::string osStr;
129 374 : const char *pszSQLCommand = *ppszSQLCommand;
130 374 : LayerDesc oLayerDesc;
131 :
132 374 : while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
133 0 : pszSQLCommand++;
134 :
135 374 : const char *pszOriginalStrStart = pszSQLCommand;
136 374 : oLayerDesc.osOriginalStr = pszSQLCommand;
137 :
138 374 : osStr = OGR2SQLITEExtractUnquotedString(&pszSQLCommand);
139 :
140 374 : if (*pszSQLCommand == '.')
141 : {
142 7 : oLayerDesc.osDSName = osStr;
143 7 : pszSQLCommand++;
144 : oLayerDesc.osLayerName =
145 7 : OGR2SQLITEExtractUnquotedString(&pszSQLCommand);
146 : }
147 : else
148 : {
149 367 : oLayerDesc.osLayerName = std::move(osStr);
150 : }
151 :
152 374 : oLayerDesc.osOriginalStr.resize(pszSQLCommand - pszOriginalStrStart);
153 :
154 374 : *ppszSQLCommand = pszSQLCommand;
155 :
156 748 : return oLayerDesc;
157 : }
158 :
159 : /************************************************************************/
160 : /* OGR2SQLITEAddLayer() */
161 : /************************************************************************/
162 :
163 374 : static void OGR2SQLITEAddLayer(const char *&pszStart, int &nNum,
164 : const char *&pszSQLCommand,
165 : std::set<LayerDesc> &oSet,
166 : CPLString &osModifiedSQL)
167 : {
168 748 : CPLString osTruncated(pszStart);
169 374 : osTruncated.resize(pszSQLCommand - pszStart);
170 374 : osModifiedSQL += osTruncated;
171 374 : pszStart = pszSQLCommand;
172 374 : LayerDesc oLayerDesc = OGR2SQLITEExtractLayerDesc(&pszSQLCommand);
173 374 : bool bInsert = true;
174 374 : if (oLayerDesc.osDSName.empty())
175 : {
176 367 : osTruncated = pszStart;
177 367 : osTruncated.resize(pszSQLCommand - pszStart);
178 367 : osModifiedSQL += osTruncated;
179 : }
180 : else
181 : {
182 7 : std::set<LayerDesc>::iterator oIter = oSet.find(oLayerDesc);
183 7 : if (oIter == oSet.end())
184 : {
185 : oLayerDesc.osSubstitutedName =
186 7 : CPLString().Printf("_OGR_%d", nNum++);
187 7 : osModifiedSQL += "\"";
188 7 : osModifiedSQL += oLayerDesc.osSubstitutedName;
189 7 : osModifiedSQL += "\"";
190 : }
191 : else
192 : {
193 0 : osModifiedSQL += (*oIter).osSubstitutedName;
194 0 : bInsert = false;
195 : }
196 : }
197 374 : if (bInsert)
198 : {
199 374 : oSet.insert(oLayerDesc);
200 : }
201 374 : pszStart = pszSQLCommand;
202 374 : }
203 :
204 : /************************************************************************/
205 : /* StartsAsSQLITEKeyWord() */
206 : /************************************************************************/
207 :
208 294 : static int StartsAsSQLITEKeyWord(const char *pszStr)
209 : {
210 85 : for (const char *pszKeyword : {"WHERE", "GROUP", "ORDER", "JOIN", "UNION",
211 379 : "INTERSECT", "EXCEPT", "LIMIT"})
212 : {
213 372 : if (STARTS_WITH_CI(pszStr, pszKeyword))
214 287 : return TRUE;
215 : }
216 7 : return FALSE;
217 : }
218 :
219 : /************************************************************************/
220 : /* OGR2SQLITEGetPotentialLayerNames() */
221 : /************************************************************************/
222 :
223 639 : static void OGR2SQLITEGetPotentialLayerNamesInternal(
224 : const char **ppszSQLCommand, std::set<LayerDesc> &oSetLayers,
225 : std::set<CPLString> &oSetSpatialIndex, CPLString &osModifiedSQL, int &nNum)
226 : {
227 639 : const char *pszSQLCommand = *ppszSQLCommand;
228 639 : const char *pszStart = pszSQLCommand;
229 639 : char ch = '\0';
230 639 : int nParenthesisLevel = 0;
231 639 : bool bLookforFTableName = false;
232 :
233 24729 : while ((ch = *pszSQLCommand) != '\0')
234 : {
235 24092 : if (ch == '(')
236 544 : nParenthesisLevel++;
237 23548 : else if (ch == ')')
238 : {
239 556 : nParenthesisLevel--;
240 556 : if (nParenthesisLevel < 0)
241 : {
242 2 : pszSQLCommand++;
243 2 : break;
244 : }
245 : }
246 :
247 : /* Skip literals and strings */
248 24090 : if (ch == '\'' || ch == '"')
249 : {
250 495 : char chEscapeChar = ch;
251 495 : pszSQLCommand++;
252 16948 : while ((ch = *pszSQLCommand) != '\0')
253 : {
254 16948 : if (ch == chEscapeChar && pszSQLCommand[1] == chEscapeChar)
255 0 : pszSQLCommand++;
256 16948 : else if (ch == chEscapeChar)
257 : {
258 495 : pszSQLCommand++;
259 495 : break;
260 : }
261 16453 : pszSQLCommand++;
262 495 : }
263 : }
264 :
265 23595 : else if (STARTS_WITH_CI(pszSQLCommand, "ogr_layer_"))
266 : {
267 182 : while (*pszSQLCommand != '\0' && *pszSQLCommand != '(')
268 172 : pszSQLCommand++;
269 :
270 10 : if (*pszSQLCommand != '(')
271 0 : break;
272 :
273 10 : pszSQLCommand++;
274 10 : nParenthesisLevel++;
275 :
276 10 : while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
277 0 : pszSQLCommand++;
278 :
279 10 : OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand, oSetLayers,
280 : osModifiedSQL);
281 : }
282 :
283 23585 : else if (bLookforFTableName &&
284 7 : STARTS_WITH_CI(pszSQLCommand, "f_table_name") &&
285 1 : (pszSQLCommand[strlen("f_table_name")] == '=' ||
286 1 : isspace(static_cast<unsigned char>(
287 1 : pszSQLCommand[strlen("f_table_name")]))))
288 : {
289 1 : pszSQLCommand += strlen("f_table_name");
290 :
291 2 : while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
292 1 : pszSQLCommand++;
293 :
294 1 : if (*pszSQLCommand == '=')
295 : {
296 1 : pszSQLCommand++;
297 :
298 2 : while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
299 1 : pszSQLCommand++;
300 :
301 : oSetSpatialIndex.insert(
302 1 : OGR2SQLITEExtractUnquotedString(&pszSQLCommand));
303 : }
304 :
305 1 : bLookforFTableName = false;
306 : }
307 :
308 23584 : else if (STARTS_WITH_CI(pszSQLCommand, "FROM") &&
309 467 : isspace(
310 467 : static_cast<unsigned char>(pszSQLCommand[strlen("FROM")])))
311 : {
312 338 : pszSQLCommand += strlen("FROM") + 1;
313 :
314 338 : while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
315 0 : pszSQLCommand++;
316 :
317 338 : if (STARTS_WITH_CI(pszSQLCommand, "SpatialIndex") &&
318 1 : isspace(static_cast<unsigned char>(
319 1 : pszSQLCommand[strlen("SpatialIndex")])))
320 : {
321 1 : pszSQLCommand += strlen("SpatialIndex") + 1;
322 :
323 1 : bLookforFTableName = true;
324 :
325 1 : continue;
326 : }
327 :
328 337 : if (*pszSQLCommand == '(')
329 : {
330 2 : pszSQLCommand++;
331 :
332 2 : CPLString osTruncated(pszStart);
333 2 : osTruncated.resize(pszSQLCommand - pszStart);
334 2 : osModifiedSQL += osTruncated;
335 :
336 2 : OGR2SQLITEGetPotentialLayerNamesInternal(
337 : &pszSQLCommand, oSetLayers, oSetSpatialIndex, osModifiedSQL,
338 : nNum);
339 :
340 2 : pszStart = pszSQLCommand;
341 : }
342 : else
343 335 : OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand, oSetLayers,
344 : osModifiedSQL);
345 :
346 349 : while (*pszSQLCommand != '\0')
347 : {
348 303 : if (isspace(static_cast<unsigned char>(*pszSQLCommand)))
349 : {
350 295 : pszSQLCommand++;
351 295 : while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
352 0 : pszSQLCommand++;
353 :
354 295 : if (STARTS_WITH_CI(pszSQLCommand, "AS"))
355 : {
356 0 : pszSQLCommand += 2;
357 0 : while (
358 0 : isspace(static_cast<unsigned char>(*pszSQLCommand)))
359 0 : pszSQLCommand++;
360 : }
361 :
362 : /* Skip alias */
363 295 : if (*pszSQLCommand != '\0' && *pszSQLCommand != ',')
364 : {
365 294 : if (StartsAsSQLITEKeyWord(pszSQLCommand))
366 287 : break;
367 7 : OGR2SQLITEExtractUnquotedString(&pszSQLCommand);
368 : }
369 : }
370 8 : else if (*pszSQLCommand == ',')
371 : {
372 4 : pszSQLCommand++;
373 8 : while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
374 4 : pszSQLCommand++;
375 :
376 4 : if (*pszSQLCommand == '(')
377 : {
378 0 : pszSQLCommand++;
379 :
380 0 : CPLString osTruncated(pszStart);
381 0 : osTruncated.resize(pszSQLCommand - pszStart);
382 0 : osModifiedSQL += osTruncated;
383 :
384 0 : OGR2SQLITEGetPotentialLayerNamesInternal(
385 : &pszSQLCommand, oSetLayers, oSetSpatialIndex,
386 : osModifiedSQL, nNum);
387 :
388 0 : pszStart = pszSQLCommand;
389 : }
390 : else
391 4 : OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand,
392 : oSetLayers, osModifiedSQL);
393 : }
394 : else
395 4 : break;
396 337 : }
397 : }
398 23246 : else if (STARTS_WITH_CI(pszSQLCommand, "JOIN") &&
399 9 : isspace(
400 9 : static_cast<unsigned char>(pszSQLCommand[strlen("JOIN")])))
401 : {
402 5 : pszSQLCommand += strlen("JOIN") + 1;
403 5 : OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand, oSetLayers,
404 : osModifiedSQL);
405 : }
406 23241 : else if (STARTS_WITH_CI(pszSQLCommand, "INTO") &&
407 12 : isspace(
408 12 : static_cast<unsigned char>(pszSQLCommand[strlen("INTO")])))
409 : {
410 12 : pszSQLCommand += strlen("INTO") + 1;
411 12 : OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand, oSetLayers,
412 : osModifiedSQL);
413 : }
414 23229 : else if (STARTS_WITH_CI(pszSQLCommand, "UPDATE") &&
415 8 : isspace(static_cast<unsigned char>(
416 8 : pszSQLCommand[strlen("UPDATE")])))
417 : {
418 8 : pszSQLCommand += strlen("UPDATE") + 1;
419 8 : OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand, oSetLayers,
420 : osModifiedSQL);
421 : }
422 : else
423 23221 : pszSQLCommand++;
424 : }
425 :
426 639 : CPLString osTruncated(pszStart);
427 639 : osTruncated.resize(pszSQLCommand - pszStart);
428 639 : osModifiedSQL += osTruncated;
429 :
430 639 : *ppszSQLCommand = pszSQLCommand;
431 639 : }
432 :
433 637 : static void OGR2SQLITEGetPotentialLayerNames(
434 : const char *pszSQLCommand, std::set<LayerDesc> &oSetLayers,
435 : std::set<CPLString> &oSetSpatialIndex, CPLString &osModifiedSQL)
436 : {
437 637 : int nNum = 1;
438 637 : OGR2SQLITEGetPotentialLayerNamesInternal(
439 : &pszSQLCommand, oSetLayers, oSetSpatialIndex, osModifiedSQL, nNum);
440 637 : }
441 :
442 : /************************************************************************/
443 : /* OGRSQLiteGetReferencedLayers() */
444 : /************************************************************************/
445 :
446 1 : std::set<LayerDesc> OGRSQLiteGetReferencedLayers(const char *pszStatement)
447 : {
448 : /* -------------------------------------------------------------------- */
449 : /* Analyze the statement to determine which tables will be used. */
450 : /* -------------------------------------------------------------------- */
451 1 : std::set<LayerDesc> oSetLayers;
452 2 : std::set<CPLString> oSetSpatialIndex;
453 2 : CPLString osModifiedSQL;
454 1 : OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers, oSetSpatialIndex,
455 : osModifiedSQL);
456 :
457 2 : return oSetLayers;
458 : }
459 :
460 : #ifndef HAVE_SQLITE3EXT_H
461 : OGRLayer *OGRSQLiteExecuteSQL(GDALDataset *, const char *, OGRGeometry *,
462 : const char *)
463 : {
464 : CPLError(CE_Failure, CPLE_NotSupported,
465 : "SQL SQLite dialect not supported due to GDAL being built "
466 : "without sqlite3ext.h header");
467 : return nullptr;
468 : }
469 :
470 : #else
471 :
472 : /************************************************************************/
473 : /* OGRSQLiteExecuteSQLLayer */
474 : /************************************************************************/
475 :
476 : class OGRSQLiteExecuteSQLLayer final : public OGRSQLiteSelectLayer
477 : {
478 : char *m_pszTmpDBName = nullptr;
479 : bool m_bStringsAsUTF8 = false;
480 :
481 : CPL_DISALLOW_COPY_ASSIGN(OGRSQLiteExecuteSQLLayer)
482 :
483 : public:
484 : OGRSQLiteExecuteSQLLayer(char *pszTmpDBName, OGRSQLiteDataSource *poDS,
485 : const CPLString &osSQL, sqlite3_stmt *hStmt,
486 : bool bUseStatementForGetNextFeature,
487 : bool bEmptyLayer, bool bCanReopenBaseDS,
488 : bool bStringsAsUTF8);
489 : virtual ~OGRSQLiteExecuteSQLLayer();
490 :
491 : int TestCapability(const char *pszCap) override;
492 : };
493 :
494 : /************************************************************************/
495 : /* OGRSQLiteExecuteSQLLayer() */
496 : /************************************************************************/
497 :
498 595 : OGRSQLiteExecuteSQLLayer::OGRSQLiteExecuteSQLLayer(
499 : char *pszTmpDBNameIn, OGRSQLiteDataSource *poDSIn, const CPLString &osSQL,
500 : sqlite3_stmt *hStmtIn, bool bUseStatementForGetNextFeature,
501 595 : bool bEmptyLayer, bool bCanReopenBaseDS, bool bStringsAsUTF8)
502 : : OGRSQLiteSelectLayer(poDSIn, osSQL, hStmtIn,
503 : bUseStatementForGetNextFeature, bEmptyLayer, true,
504 : bCanReopenBaseDS),
505 595 : m_pszTmpDBName(pszTmpDBNameIn), m_bStringsAsUTF8(bStringsAsUTF8)
506 : {
507 595 : }
508 :
509 : /************************************************************************/
510 : /* ~OGRSQLiteExecuteSQLLayer() */
511 : /************************************************************************/
512 :
513 1188 : OGRSQLiteExecuteSQLLayer::~OGRSQLiteExecuteSQLLayer()
514 : {
515 : // This is a bit peculiar: we must "finalize" the OGRLayer, since
516 : // it has objects that depend on the datasource, that we are just
517 : // going to destroy afterwards. The issue here is that we destroy
518 : // our own datasource,
519 594 : Finalize();
520 :
521 594 : delete m_poDS;
522 594 : VSIUnlink(m_pszTmpDBName);
523 594 : CPLFree(m_pszTmpDBName);
524 1188 : }
525 :
526 : /************************************************************************/
527 : /* TestCapability() */
528 : /************************************************************************/
529 :
530 1 : int OGRSQLiteExecuteSQLLayer::TestCapability(const char *pszCap)
531 : {
532 1 : if (EQUAL(pszCap, OLCStringsAsUTF8))
533 1 : return m_bStringsAsUTF8;
534 0 : return OGRSQLiteSelectLayer::TestCapability(pszCap);
535 : }
536 :
537 : /************************************************************************/
538 : /* OGR2SQLITE_IgnoreAllFieldsExceptGeometry() */
539 : /************************************************************************/
540 :
541 : #ifdef HAVE_SPATIALITE
542 2 : static void OGR2SQLITE_IgnoreAllFieldsExceptGeometry(OGRLayer *poLayer)
543 : {
544 2 : char **papszIgnored = nullptr;
545 2 : papszIgnored = CSLAddString(papszIgnored, "OGR_STYLE");
546 2 : OGRFeatureDefn *poFeatureDefn = poLayer->GetLayerDefn();
547 4 : for (int i = 0; i < poFeatureDefn->GetFieldCount(); i++)
548 : {
549 2 : papszIgnored = CSLAddString(
550 2 : papszIgnored, poFeatureDefn->GetFieldDefn(i)->GetNameRef());
551 : }
552 2 : poLayer->SetIgnoredFields(const_cast<const char **>(papszIgnored));
553 2 : CSLDestroy(papszIgnored);
554 2 : }
555 : #endif
556 :
557 : /************************************************************************/
558 : /* OGR2SQLITEDealWithSpatialColumn() */
559 : /************************************************************************/
560 : #if HAVE_SPATIALITE
561 : #define WHEN_SPATIALITE(arg) arg
562 : #else
563 : #define WHEN_SPATIALITE(arg)
564 : #endif
565 :
566 251 : static int OGR2SQLITEDealWithSpatialColumn(
567 : OGRLayer *poLayer, int iGeomCol, const LayerDesc &oLayerDesc,
568 : const CPLString &osTableName, OGRSQLiteDataSource *poSQLiteDS, sqlite3 *hDB,
569 : bool bSpatialiteDB, const std::set<LayerDesc> &WHEN_SPATIALITE(oSetLayers),
570 : const std::set<CPLString> &WHEN_SPATIALITE(oSetSpatialIndex))
571 : {
572 : OGRGeomFieldDefn *poGeomField =
573 251 : poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomCol);
574 502 : CPLString osGeomColRaw;
575 251 : if (iGeomCol == 0)
576 246 : osGeomColRaw = OGR2SQLITE_GetNameForGeometryColumn(poLayer);
577 : else
578 5 : osGeomColRaw = poGeomField->GetNameRef();
579 251 : const char *pszGeomColRaw = osGeomColRaw.c_str();
580 :
581 502 : CPLString osGeomColEscaped(SQLEscapeLiteral(pszGeomColRaw));
582 251 : const char *pszGeomColEscaped = osGeomColEscaped.c_str();
583 :
584 502 : CPLString osLayerNameEscaped(SQLEscapeLiteral(osTableName));
585 251 : const char *pszLayerNameEscaped = osLayerNameEscaped.c_str();
586 :
587 : CPLString osIdxNameRaw(
588 502 : CPLSPrintf("idx_%s_%s", oLayerDesc.osLayerName.c_str(), pszGeomColRaw));
589 502 : CPLString osIdxNameEscaped(SQLEscapeName(osIdxNameRaw));
590 :
591 : /* Make sure that the SRS is injected in spatial_ref_sys */
592 251 : const OGRSpatialReference *poSRS = poGeomField->GetSpatialRef();
593 251 : if (iGeomCol == 0 && poSRS == nullptr)
594 221 : poSRS = poLayer->GetSpatialRef();
595 251 : int nSRSId = poSQLiteDS->GetUndefinedSRID();
596 251 : if (poSRS != nullptr)
597 30 : nSRSId = poSQLiteDS->FetchSRSId(poSRS);
598 :
599 502 : CPLString osSQL;
600 : #ifdef HAVE_SPATIALITE
601 251 : bool bCreateSpatialIndex = false;
602 : #endif
603 251 : if (!bSpatialiteDB)
604 : {
605 : osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
606 : "f_geometry_column, geometry_format, geometry_type, "
607 : "coord_dimension, srid) "
608 : "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)",
609 : pszLayerNameEscaped, pszGeomColEscaped,
610 58 : static_cast<int>(wkbFlatten(poLayer->GetGeomType())),
611 116 : wkbHasZ(poLayer->GetGeomType()) ? 3 : 2, nSRSId);
612 : }
613 : #ifdef HAVE_SPATIALITE
614 : else
615 : {
616 : /* We detect the need for creating a spatial index by 2 means : */
617 :
618 : /* 1) if there's an explicit reference to a
619 : * 'idx_layername_geometrycolumn' */
620 : /* table in the SQL --> old/traditional way of requesting spatial
621 : * indices */
622 : /* with spatialite. */
623 :
624 193 : std::set<LayerDesc>::const_iterator oIter2 = oSetLayers.begin();
625 392 : for (; oIter2 != oSetLayers.end(); ++oIter2)
626 : {
627 200 : const LayerDesc &oLayerDescIter = *oIter2;
628 200 : if (EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw))
629 : {
630 1 : bCreateSpatialIndex = true;
631 1 : break;
632 : }
633 : }
634 :
635 : /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name =
636 : * 'layername' */
637 193 : if (!bCreateSpatialIndex)
638 : {
639 : std::set<CPLString>::const_iterator oIter3 =
640 192 : oSetSpatialIndex.begin();
641 193 : for (; oIter3 != oSetSpatialIndex.end(); ++oIter3)
642 : {
643 2 : const CPLString &osNameIter = *oIter3;
644 2 : if (EQUAL(osNameIter, oLayerDesc.osLayerName))
645 : {
646 1 : bCreateSpatialIndex = true;
647 1 : break;
648 : }
649 : }
650 : }
651 :
652 193 : if (poSQLiteDS->HasSpatialite4Layout())
653 : {
654 193 : const auto eGeomType = poLayer->GetGeomType();
655 193 : int nGeomType = eGeomType;
656 193 : int nCoordDimension = 2;
657 193 : if (wkbHasZ(eGeomType))
658 : {
659 1 : nGeomType += 1000;
660 1 : nCoordDimension = 3;
661 : }
662 :
663 : osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
664 : "f_geometry_column, geometry_type, coord_dimension, "
665 : "srid, spatial_index_enabled) "
666 : "VALUES (Lower('%s'),Lower('%s'),%d ,%d ,%d, %d)",
667 : pszLayerNameEscaped, pszGeomColEscaped, nGeomType,
668 : nCoordDimension, nSRSId,
669 193 : static_cast<int>(bCreateSpatialIndex));
670 : }
671 : else
672 : {
673 : const char *pszGeometryType =
674 0 : OGRToOGCGeomType(poLayer->GetGeomType());
675 0 : if (pszGeometryType[0] == '\0')
676 0 : pszGeometryType = "GEOMETRY";
677 :
678 : osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
679 : "f_geometry_column, type, coord_dimension, "
680 : "srid, spatial_index_enabled) "
681 : "VALUES ('%s','%s','%s','%s',%d, %d)",
682 : pszLayerNameEscaped, pszGeomColEscaped,
683 : pszGeometryType,
684 0 : wkbHasZ(poLayer->GetGeomType()) ? "XYZ" : "XY", nSRSId,
685 0 : static_cast<int>(bCreateSpatialIndex));
686 : }
687 : }
688 : #endif // HAVE_SPATIALITE
689 251 : char *pszErrMsg = nullptr;
690 251 : int rc = sqlite3_exec(hDB, osSQL.c_str(), nullptr, nullptr, &pszErrMsg);
691 251 : if (pszErrMsg != nullptr)
692 : {
693 2 : CPLDebug("SQLITE", "%s -> %s", osSQL.c_str(), pszErrMsg);
694 2 : sqlite3_free(pszErrMsg);
695 : }
696 :
697 : #ifdef HAVE_SPATIALITE
698 : /* -------------------------------------------------------------------- */
699 : /* Should we create a spatial index ?. */
700 : /* -------------------------------------------------------------------- */
701 251 : if (!bSpatialiteDB || !bCreateSpatialIndex)
702 249 : return rc == SQLITE_OK;
703 :
704 2 : CPLDebug("SQLITE", "Create spatial index %s", osIdxNameRaw.c_str());
705 :
706 : /* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */
707 : #ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
708 : osSQL.Printf(
709 : "CREATE VIRTUAL TABLE \"%s\" USING "
710 : "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)",
711 : osIdxNameEscaped.c_str(), nExtraDS,
712 : SQLEscapeLiteral(oLayerDesc.osLayerName).c_str());
713 :
714 : rc = sqlite3_exec(hDB, osSQL.c_str(), NULL, NULL, NULL);
715 : if (rc != SQLITE_OK)
716 : {
717 : CPLDebug("SQLITE", "Error occurred during spatial index creation : %s",
718 : sqlite3_errmsg(hDB));
719 : }
720 : #else // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
721 2 : rc = sqlite3_exec(hDB, "BEGIN", nullptr, nullptr, nullptr);
722 :
723 : osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" "
724 : "USING rtree(pkid, xmin, xmax, ymin, ymax)",
725 2 : osIdxNameEscaped.c_str());
726 :
727 2 : if (rc == SQLITE_OK)
728 2 : rc = sqlite3_exec(hDB, osSQL.c_str(), nullptr, nullptr, nullptr);
729 :
730 2 : sqlite3_stmt *hStmt = nullptr;
731 2 : if (rc == SQLITE_OK)
732 : {
733 : const char *pszInsertInto =
734 2 : CPLSPrintf("INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) "
735 : "VALUES (?,?,?,?,?)",
736 : osIdxNameEscaped.c_str());
737 2 : rc = sqlite3_prepare_v2(hDB, pszInsertInto, -1, &hStmt, nullptr);
738 : }
739 :
740 2 : OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer);
741 2 : poLayer->ResetReading();
742 :
743 2 : OGRFeature *poFeature = nullptr;
744 2 : OGREnvelope sEnvelope;
745 12 : while (rc == SQLITE_OK &&
746 6 : (poFeature = poLayer->GetNextFeature()) != nullptr)
747 : {
748 4 : OGRGeometry *poGeom = poFeature->GetGeometryRef();
749 4 : if (poGeom != nullptr && !poGeom->IsEmpty())
750 : {
751 4 : poGeom->getEnvelope(&sEnvelope);
752 4 : sqlite3_bind_int64(hStmt, 1,
753 4 : static_cast<sqlite3_int64>(poFeature->GetFID()));
754 4 : sqlite3_bind_double(hStmt, 2, sEnvelope.MinX);
755 4 : sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX);
756 4 : sqlite3_bind_double(hStmt, 4, sEnvelope.MinY);
757 4 : sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY);
758 4 : rc = sqlite3_step(hStmt);
759 4 : if (rc == SQLITE_OK || rc == SQLITE_DONE)
760 4 : rc = sqlite3_reset(hStmt);
761 : }
762 4 : delete poFeature;
763 : }
764 :
765 2 : poLayer->SetIgnoredFields(nullptr);
766 :
767 2 : sqlite3_finalize(hStmt);
768 :
769 2 : if (rc == SQLITE_OK)
770 2 : rc = sqlite3_exec(hDB, "COMMIT", nullptr, nullptr, nullptr);
771 : else
772 : {
773 0 : CPLDebug("SQLITE", "Error occurred during spatial index creation : %s",
774 : sqlite3_errmsg(hDB));
775 0 : rc = sqlite3_exec(hDB, "ROLLBACK", nullptr, nullptr, nullptr);
776 : }
777 : #endif // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
778 :
779 : #endif // HAVE_SPATIALITE
780 :
781 2 : return rc == SQLITE_OK;
782 : }
783 :
784 : /************************************************************************/
785 : /* OGRSQLiteExecuteSQL() */
786 : /************************************************************************/
787 :
788 643 : OGRLayer *OGRSQLiteExecuteSQL(GDALDataset *poDS, const char *pszStatement,
789 : OGRGeometry *poSpatialFilter,
790 : CPL_UNUSED const char *pszDialect)
791 : {
792 643 : while (*pszStatement != '\0' &&
793 643 : isspace(static_cast<unsigned char>(*pszStatement)))
794 0 : pszStatement++;
795 :
796 643 : if (STARTS_WITH_CI(pszStatement, "ALTER TABLE ") ||
797 642 : STARTS_WITH_CI(pszStatement, "DROP TABLE ") ||
798 641 : STARTS_WITH_CI(pszStatement, "CREATE INDEX ") ||
799 640 : STARTS_WITH_CI(pszStatement, "DROP INDEX "))
800 : {
801 4 : CPLError(CE_Failure, CPLE_NotSupported,
802 : "SQL command not supported with SQLite dialect. "
803 : "Use OGRSQL dialect instead.");
804 4 : return nullptr;
805 : }
806 647 : else if (STARTS_WITH_CI(pszStatement, "CREATE VIRTUAL TABLE ") &&
807 8 : CPLTestBool(CPLGetConfigOption(
808 : "OGR_SQLITE_DIALECT_ALLOW_CREATE_VIRTUAL_TABLE", "NO")))
809 : {
810 : // for ogr_virtualogr.py::ogr_virtualogr_run_sql() only. This is
811 : // just a convenient way of testing VirtualOGR() with
812 : // CREATE VIRTUAL TABLE ... USING VirtualOGR(...)
813 : // but there is no possible use of that given we run that into
814 : // an ephemeral database.
815 : }
816 : else
817 : {
818 632 : bool bUnderstoodStatement = false;
819 134 : for (const char *pszKeyword : {"SELECT", "WITH", "EXPLAIN", "INSERT",
820 766 : "UPDATE", "DELETE", "REPLACE"})
821 : {
822 763 : if (STARTS_WITH_CI(pszStatement, pszKeyword) &&
823 629 : std::isspace(static_cast<unsigned char>(
824 629 : pszStatement[strlen(pszKeyword)])))
825 : {
826 629 : bUnderstoodStatement = true;
827 629 : break;
828 : }
829 : }
830 632 : if (!bUnderstoodStatement)
831 : {
832 3 : CPLError(CE_Failure, CPLE_NotSupported, "Unsupported SQL command.");
833 3 : return nullptr;
834 : }
835 : }
836 :
837 636 : char *pszTmpDBName = static_cast<char *>(CPLMalloc(256));
838 636 : snprintf(pszTmpDBName, 256, "%s", VSIMemGenerateHiddenFilename("temp.db"));
839 :
840 636 : OGRSQLiteDataSource *poSQLiteDS = nullptr;
841 636 : bool bSpatialiteDB = false;
842 :
843 : /* -------------------------------------------------------------------- */
844 : /* Create in-memory sqlite/spatialite DB */
845 : /* -------------------------------------------------------------------- */
846 :
847 : #ifdef HAVE_SPATIALITE
848 :
849 : /* -------------------------------------------------------------------- */
850 : /* Creating an empty SpatiaLite DB (with spatial_ref_sys populated */
851 : /* has a significant cost. So at the first attempt, let's make */
852 : /* one and cache it for later use. */
853 : /* -------------------------------------------------------------------- */
854 : #if 1
855 : static size_t nEmptyDBSize = 0;
856 : static GByte *pabyEmptyDB = nullptr;
857 : {
858 : static CPLMutex *hMutex = nullptr;
859 1272 : CPLMutexHolder oMutexHolder(&hMutex);
860 : static bool bTried = false;
861 636 : if (!bTried && CPLTestBool(CPLGetConfigOption(
862 : "OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")))
863 : {
864 3 : bTried = true;
865 3 : char *pszCachedFilename = static_cast<char *>(CPLMalloc(256));
866 3 : snprintf(pszCachedFilename, 256, "%s",
867 : VSIMemGenerateHiddenFilename("reference.db"));
868 3 : char **papszOptions = CSLAddString(nullptr, "SPATIALITE=YES");
869 3 : OGRSQLiteDataSource *poCachedDS = new OGRSQLiteDataSource();
870 : const int nRet =
871 3 : poCachedDS->Create(pszCachedFilename, papszOptions);
872 3 : CSLDestroy(papszOptions);
873 3 : papszOptions = nullptr;
874 3 : delete poCachedDS;
875 3 : if (nRet)
876 : {
877 : /* Note: the reference file keeps the ownership of the data, so
878 : * that */
879 : /* it gets released with VSICleanupFileManager() */
880 3 : vsi_l_offset nEmptyDBSizeLarge = 0;
881 3 : pabyEmptyDB = VSIGetMemFileBuffer(pszCachedFilename,
882 : &nEmptyDBSizeLarge, FALSE);
883 3 : nEmptyDBSize = static_cast<size_t>(nEmptyDBSizeLarge);
884 : }
885 3 : CPLFree(pszCachedFilename);
886 : }
887 : }
888 :
889 : /* The following configuration option is useful mostly for debugging/testing
890 : */
891 1272 : if (pabyEmptyDB != nullptr &&
892 636 : CPLTestBool(
893 : CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")))
894 : {
895 : GByte *pabyEmptyDBClone =
896 526 : static_cast<GByte *>(VSI_MALLOC_VERBOSE(nEmptyDBSize));
897 526 : if (pabyEmptyDBClone == nullptr)
898 : {
899 0 : CPLFree(pszTmpDBName);
900 0 : return nullptr;
901 : }
902 526 : memcpy(pabyEmptyDBClone, pabyEmptyDB, nEmptyDBSize);
903 526 : VSIFCloseL(VSIFileFromMemBuffer(pszTmpDBName, pabyEmptyDBClone,
904 : nEmptyDBSize, TRUE));
905 :
906 526 : poSQLiteDS = new OGRSQLiteDataSource();
907 526 : GDALOpenInfo oOpenInfo(pszTmpDBName, GDAL_OF_VECTOR | GDAL_OF_UPDATE);
908 : CPLConfigOptionSetter oSetter("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO",
909 526 : false);
910 526 : const int nRet = poSQLiteDS->Open(&oOpenInfo);
911 526 : if (!nRet)
912 : {
913 : /* should not happen really ! */
914 0 : delete poSQLiteDS;
915 0 : VSIUnlink(pszTmpDBName);
916 0 : CPLFree(pszTmpDBName);
917 0 : return nullptr;
918 : }
919 526 : bSpatialiteDB = true;
920 : }
921 : #else
922 : /* No caching version */
923 : poSQLiteDS = new OGRSQLiteDataSource();
924 : char **papszOptions = CSLAddString(NULL, "SPATIALITE=YES");
925 : {
926 : CPLConfigOptionSetter oSetter("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO",
927 : false);
928 : const int nRet = poSQLiteDS->Create(pszTmpDBName, papszOptions);
929 : CSLDestroy(papszOptions);
930 : papszOptions = nullptr;
931 : if (nRet)
932 : {
933 : bSpatialiteDB = true;
934 : }
935 : }
936 : #endif
937 :
938 : else
939 : {
940 110 : delete poSQLiteDS;
941 110 : poSQLiteDS = nullptr;
942 : #else // HAVE_SPATIALITE
943 : if (true)
944 : {
945 : #endif // HAVE_SPATIALITE
946 :
947 : // cppcheck-suppress redundantAssignment
948 110 : poSQLiteDS = new OGRSQLiteDataSource();
949 : CPLConfigOptionSetter oSetter("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO",
950 110 : false);
951 110 : const int nRet = poSQLiteDS->Create(pszTmpDBName, nullptr);
952 110 : if (!nRet)
953 : {
954 0 : delete poSQLiteDS;
955 0 : VSIUnlink(pszTmpDBName);
956 0 : CPLFree(pszTmpDBName);
957 0 : return nullptr;
958 : }
959 : }
960 :
961 : /* -------------------------------------------------------------------- */
962 : /* Attach the Virtual Table OGR2SQLITE module to it. */
963 : /* -------------------------------------------------------------------- */
964 636 : OGR2SQLITEModule *poModule = OGR2SQLITE_Setup(poDS, poSQLiteDS);
965 636 : if (!poModule)
966 : {
967 0 : delete poSQLiteDS;
968 0 : VSIUnlink(pszTmpDBName);
969 0 : CPLFree(pszTmpDBName);
970 0 : return nullptr;
971 : }
972 636 : sqlite3 *hDB = poSQLiteDS->GetDB();
973 :
974 : /* -------------------------------------------------------------------- */
975 : /* Analysze the statement to determine which tables will be used. */
976 : /* -------------------------------------------------------------------- */
977 1272 : std::set<LayerDesc> oSetLayers;
978 1272 : std::set<CPLString> oSetSpatialIndex;
979 1272 : CPLString osModifiedSQL;
980 636 : OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers, oSetSpatialIndex,
981 : osModifiedSQL);
982 636 : std::set<LayerDesc>::iterator oIter = oSetLayers.begin();
983 :
984 636 : if (strcmp(pszStatement, osModifiedSQL.c_str()) != 0)
985 6 : CPLDebug("OGR", "Modified SQL: %s", osModifiedSQL.c_str());
986 636 : pszStatement = osModifiedSQL.c_str(); /* do not use it anymore */
987 :
988 : const bool bFoundOGRStyle =
989 636 : (osModifiedSQL.ifind("OGR_STYLE") != std::string::npos);
990 :
991 : /* -------------------------------------------------------------------- */
992 : /* For each of those tables, create a Virtual Table. */
993 : /* -------------------------------------------------------------------- */
994 636 : OGRLayer *poSingleSrcLayer = nullptr;
995 636 : bool bStringsAsUTF8 = true;
996 1005 : for (; oIter != oSetLayers.end(); ++oIter)
997 : {
998 371 : const LayerDesc &oLayerDesc = *oIter;
999 : /*CPLDebug("OGR", "Layer desc : %s, %s, %s, %s",
1000 : oLayerDesc.osOriginalStr.c_str(),
1001 : oLayerDesc.osSubstitutedName.c_str(),
1002 : oLayerDesc.osDSName.c_str(),
1003 : oLayerDesc.osLayerName.c_str());*/
1004 :
1005 371 : CPLString osSQL;
1006 371 : OGRLayer *poLayer = nullptr;
1007 371 : CPLString osTableName;
1008 371 : int nExtraDS = -1;
1009 371 : if (oLayerDesc.osDSName.empty())
1010 : {
1011 364 : poLayer = poDS->GetLayerByName(oLayerDesc.osLayerName);
1012 : /* Might be a false positive (unlikely) */
1013 364 : if (poLayer == nullptr)
1014 8 : continue;
1015 :
1016 356 : osTableName = oLayerDesc.osLayerName;
1017 : }
1018 : else
1019 : {
1020 : auto poOtherDS = std::unique_ptr<GDALDataset>(
1021 : GDALDataset::Open(oLayerDesc.osDSName, GDAL_OF_VECTOR, nullptr,
1022 7 : nullptr, nullptr));
1023 7 : if (poOtherDS == nullptr)
1024 : {
1025 1 : CPLError(CE_Failure, CPLE_AppDefined,
1026 : "Cannot open datasource '%s'",
1027 : oLayerDesc.osDSName.c_str());
1028 1 : delete poSQLiteDS;
1029 1 : VSIUnlink(pszTmpDBName);
1030 1 : CPLFree(pszTmpDBName);
1031 1 : return nullptr;
1032 : }
1033 :
1034 6 : poLayer = poOtherDS->GetLayerByName(oLayerDesc.osLayerName);
1035 6 : if (poLayer == nullptr)
1036 : {
1037 1 : CPLError(CE_Failure, CPLE_AppDefined,
1038 : "Cannot find layer '%s' in '%s'",
1039 : oLayerDesc.osLayerName.c_str(),
1040 : oLayerDesc.osDSName.c_str());
1041 1 : delete poSQLiteDS;
1042 1 : VSIUnlink(pszTmpDBName);
1043 1 : CPLFree(pszTmpDBName);
1044 1 : return nullptr;
1045 : }
1046 :
1047 5 : osTableName = oLayerDesc.osSubstitutedName;
1048 :
1049 5 : nExtraDS = OGR2SQLITE_AddExtraDS(poModule, poOtherDS.release());
1050 : }
1051 :
1052 361 : if (!poLayer->TestCapability(OLCStringsAsUTF8))
1053 348 : bStringsAsUTF8 = false;
1054 :
1055 361 : if (oSetLayers.size() == 1)
1056 347 : poSingleSrcLayer = poLayer;
1057 :
1058 : osSQL.Printf(
1059 : "CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d,%d)",
1060 722 : SQLEscapeName(osTableName).c_str(), nExtraDS,
1061 722 : SQLEscapeLiteral(oLayerDesc.osLayerName).c_str(),
1062 1083 : bFoundOGRStyle ? 1 : 0, TRUE /*bExposeOGRNativeData*/);
1063 :
1064 361 : char *pszErrMsg = nullptr;
1065 361 : int rc = sqlite3_exec(hDB, osSQL.c_str(), nullptr, nullptr, &pszErrMsg);
1066 361 : if (rc != SQLITE_OK)
1067 : {
1068 0 : CPLError(CE_Failure, CPLE_AppDefined,
1069 : "Cannot create virtual table for layer '%s' : %s",
1070 : osTableName.c_str(), pszErrMsg);
1071 0 : sqlite3_free(pszErrMsg);
1072 0 : continue;
1073 : }
1074 :
1075 612 : for (int i = 0; i < poLayer->GetLayerDefn()->GetGeomFieldCount(); i++)
1076 : {
1077 251 : OGR2SQLITEDealWithSpatialColumn(poLayer, i, oLayerDesc, osTableName,
1078 : poSQLiteDS, hDB, bSpatialiteDB,
1079 : oSetLayers, oSetSpatialIndex);
1080 : }
1081 : }
1082 :
1083 : /* -------------------------------------------------------------------- */
1084 : /* Reload, so that virtual tables are recognized */
1085 : /* -------------------------------------------------------------------- */
1086 634 : poSQLiteDS->ReloadLayers();
1087 :
1088 : /* -------------------------------------------------------------------- */
1089 : /* Prepare the statement. */
1090 : /* -------------------------------------------------------------------- */
1091 : /* This will speed-up layer creation */
1092 : /* ORDER BY are costly to evaluate and are not necessary to establish */
1093 : /* the layer definition. */
1094 634 : bool bUseStatementForGetNextFeature = true;
1095 634 : bool bEmptyLayer = false;
1096 :
1097 634 : sqlite3_stmt *hSQLStmt = nullptr;
1098 634 : int rc = sqlite3_prepare_v2(hDB, pszStatement, -1, &hSQLStmt, nullptr);
1099 :
1100 634 : if (rc != SQLITE_OK)
1101 : {
1102 3 : CPLError(CE_Failure, CPLE_AppDefined,
1103 : "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n %s", pszStatement,
1104 : sqlite3_errmsg(hDB));
1105 :
1106 3 : if (hSQLStmt != nullptr)
1107 : {
1108 0 : sqlite3_finalize(hSQLStmt);
1109 : }
1110 :
1111 3 : delete poSQLiteDS;
1112 3 : VSIUnlink(pszTmpDBName);
1113 3 : CPLFree(pszTmpDBName);
1114 :
1115 3 : return nullptr;
1116 : }
1117 :
1118 : /* -------------------------------------------------------------------- */
1119 : /* Do we get a resultset? */
1120 : /* -------------------------------------------------------------------- */
1121 631 : rc = sqlite3_step(hSQLStmt);
1122 631 : if (rc != SQLITE_ROW)
1123 : {
1124 161 : if (rc != SQLITE_DONE)
1125 : {
1126 1 : CPLError(CE_Failure, CPLE_AppDefined,
1127 : "In ExecuteSQL(): sqlite3_step(%s):\n %s", pszStatement,
1128 : sqlite3_errmsg(hDB));
1129 :
1130 1 : sqlite3_finalize(hSQLStmt);
1131 :
1132 1 : delete poSQLiteDS;
1133 1 : VSIUnlink(pszTmpDBName);
1134 1 : CPLFree(pszTmpDBName);
1135 :
1136 1 : return nullptr;
1137 : }
1138 :
1139 160 : if (!STARTS_WITH_CI(pszStatement, "SELECT "))
1140 : {
1141 :
1142 35 : sqlite3_finalize(hSQLStmt);
1143 :
1144 35 : delete poSQLiteDS;
1145 35 : VSIUnlink(pszTmpDBName);
1146 35 : CPLFree(pszTmpDBName);
1147 :
1148 35 : return nullptr;
1149 : }
1150 :
1151 125 : bUseStatementForGetNextFeature = false;
1152 125 : bEmptyLayer = true;
1153 : }
1154 :
1155 : /* -------------------------------------------------------------------- */
1156 : /* Create layer. */
1157 : /* -------------------------------------------------------------------- */
1158 :
1159 595 : auto poDrv = poDS->GetDriver();
1160 : const bool bCanReopenBaseDS =
1161 595 : !(poDrv && EQUAL(poDrv->GetDescription(), "Memory"));
1162 : OGRSQLiteSelectLayer *poLayer = new OGRSQLiteExecuteSQLLayer(
1163 : pszTmpDBName, poSQLiteDS, pszStatement, hSQLStmt,
1164 : bUseStatementForGetNextFeature, bEmptyLayer, bCanReopenBaseDS,
1165 595 : bStringsAsUTF8);
1166 :
1167 595 : if (poSpatialFilter != nullptr)
1168 : {
1169 6 : const auto nErrorCounter = CPLGetErrorCounter();
1170 6 : poLayer->SetSpatialFilter(0, poSpatialFilter);
1171 8 : if (CPLGetErrorCounter() > nErrorCounter &&
1172 2 : CPLGetLastErrorType() != CE_None)
1173 : {
1174 2 : delete poLayer;
1175 2 : return nullptr;
1176 : }
1177 : }
1178 :
1179 593 : if (poSingleSrcLayer != nullptr)
1180 316 : poLayer->SetMetadata(poSingleSrcLayer->GetMetadata("NATIVE_DATA"),
1181 316 : "NATIVE_DATA");
1182 :
1183 593 : return poLayer;
1184 : }
1185 :
1186 : #endif // HAVE_SQLITE3EXT_H
|