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