Coverage Report

Created: 2025-07-23 09:13

/src/gdal/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
Line
Count
Source (jump to first uncovered line)
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
static CPLString OGR2SQLITEExtractUnquotedString(const char **ppszSQLCommand)
41
0
{
42
0
    CPLString osRet;
43
0
    const char *pszSQLCommand = *ppszSQLCommand;
44
0
    if (*pszSQLCommand == '"' || *pszSQLCommand == '\'')
45
0
    {
46
0
        const char chQuoteChar = *pszSQLCommand;
47
0
        pszSQLCommand++;
48
49
0
        while (*pszSQLCommand != '\0')
50
0
        {
51
0
            if (*pszSQLCommand == chQuoteChar &&
52
0
                pszSQLCommand[1] == chQuoteChar)
53
0
            {
54
0
                pszSQLCommand++;
55
0
                osRet += chQuoteChar;
56
0
            }
57
0
            else if (*pszSQLCommand == chQuoteChar)
58
0
            {
59
0
                pszSQLCommand++;
60
0
                break;
61
0
            }
62
0
            else
63
0
                osRet += *pszSQLCommand;
64
65
0
            pszSQLCommand++;
66
0
        }
67
0
    }
68
0
    else
69
0
    {
70
0
        bool bNotATableName = false;
71
0
        char chQuoteChar = 0;
72
0
        int nParenthesisLevel = 0;
73
0
        while (*pszSQLCommand != '\0')
74
0
        {
75
0
            if (*pszSQLCommand == chQuoteChar &&
76
0
                pszSQLCommand[1] == chQuoteChar)
77
0
            {
78
0
                osRet += *pszSQLCommand;
79
0
                pszSQLCommand++;
80
0
            }
81
0
            else if (*pszSQLCommand == chQuoteChar)
82
0
            {
83
0
                chQuoteChar = 0;
84
0
            }
85
0
            else if (chQuoteChar == 0)
86
0
            {
87
0
                if (*pszSQLCommand == '(')
88
0
                {
89
0
                    bNotATableName = true;
90
0
                    nParenthesisLevel++;
91
0
                }
92
0
                else if (*pszSQLCommand == ')')
93
0
                {
94
0
                    nParenthesisLevel--;
95
0
                    if (nParenthesisLevel < 0)
96
0
                        break;
97
0
                }
98
0
                else if (*pszSQLCommand == '"' || *pszSQLCommand == '\'')
99
0
                {
100
0
                    chQuoteChar = *pszSQLCommand;
101
0
                }
102
0
                else if (nParenthesisLevel == 0 &&
103
0
                         (isspace(static_cast<unsigned char>(*pszSQLCommand)) ||
104
0
                          *pszSQLCommand == '.' || *pszSQLCommand == ','))
105
0
                {
106
0
                    break;
107
0
                }
108
0
            }
109
110
0
            osRet += *pszSQLCommand;
111
0
            pszSQLCommand++;
112
0
        }
113
0
        if (bNotATableName)
114
0
            osRet.clear();
115
0
    }
116
117
0
    *ppszSQLCommand = pszSQLCommand;
118
119
0
    return osRet;
120
0
}
121
122
/************************************************************************/
123
/*                      OGR2SQLITEExtractLayerDesc()                    */
124
/************************************************************************/
125
126
static LayerDesc OGR2SQLITEExtractLayerDesc(const char **ppszSQLCommand)
127
0
{
128
0
    std::string osStr;
129
0
    const char *pszSQLCommand = *ppszSQLCommand;
130
0
    LayerDesc oLayerDesc;
131
132
0
    while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
133
0
        pszSQLCommand++;
134
135
0
    const char *pszOriginalStrStart = pszSQLCommand;
136
0
    oLayerDesc.osOriginalStr = pszSQLCommand;
137
138
0
    osStr = OGR2SQLITEExtractUnquotedString(&pszSQLCommand);
139
140
0
    if (*pszSQLCommand == '.')
141
0
    {
142
0
        oLayerDesc.osDSName = osStr;
143
0
        pszSQLCommand++;
144
0
        oLayerDesc.osLayerName =
145
0
            OGR2SQLITEExtractUnquotedString(&pszSQLCommand);
146
0
    }
147
0
    else
148
0
    {
149
0
        oLayerDesc.osLayerName = std::move(osStr);
150
0
    }
151
152
0
    oLayerDesc.osOriginalStr.resize(pszSQLCommand - pszOriginalStrStart);
153
154
0
    *ppszSQLCommand = pszSQLCommand;
155
156
0
    return oLayerDesc;
157
0
}
158
159
/************************************************************************/
160
/*                           OGR2SQLITEAddLayer()                       */
161
/************************************************************************/
162
163
static void OGR2SQLITEAddLayer(const char *&pszStart, int &nNum,
164
                               const char *&pszSQLCommand,
165
                               std::set<LayerDesc> &oSet,
166
                               CPLString &osModifiedSQL)
167
0
{
168
0
    CPLString osTruncated(pszStart);
169
0
    osTruncated.resize(pszSQLCommand - pszStart);
170
0
    osModifiedSQL += osTruncated;
171
0
    pszStart = pszSQLCommand;
172
0
    LayerDesc oLayerDesc = OGR2SQLITEExtractLayerDesc(&pszSQLCommand);
173
0
    bool bInsert = true;
174
0
    if (oLayerDesc.osDSName.empty())
175
0
    {
176
0
        osTruncated = pszStart;
177
0
        osTruncated.resize(pszSQLCommand - pszStart);
178
0
        osModifiedSQL += osTruncated;
179
0
    }
180
0
    else
181
0
    {
182
0
        std::set<LayerDesc>::iterator oIter = oSet.find(oLayerDesc);
183
0
        if (oIter == oSet.end())
184
0
        {
185
0
            oLayerDesc.osSubstitutedName =
186
0
                CPLString().Printf("_OGR_%d", nNum++);
187
0
            osModifiedSQL += "'";
188
0
            osModifiedSQL += oLayerDesc.osSubstitutedName;
189
0
            osModifiedSQL += "'";
190
0
        }
191
0
        else
192
0
        {
193
0
            osModifiedSQL += (*oIter).osSubstitutedName;
194
0
            bInsert = false;
195
0
        }
196
0
    }
197
0
    if (bInsert)
198
0
    {
199
0
        oSet.insert(std::move(oLayerDesc));
200
0
    }
201
0
    pszStart = pszSQLCommand;
202
0
}
203
204
/************************************************************************/
205
/*                         StartsAsSQLITEKeyWord()                      */
206
/************************************************************************/
207
208
static int StartsAsSQLITEKeyWord(const char *pszStr)
209
0
{
210
0
    for (const char *pszKeyword : {"WHERE", "GROUP", "ORDER", "JOIN", "UNION",
211
0
                                   "INTERSECT", "EXCEPT", "LIMIT"})
212
0
    {
213
0
        if (STARTS_WITH_CI(pszStr, pszKeyword))
214
0
            return TRUE;
215
0
    }
216
0
    return FALSE;
217
0
}
218
219
/************************************************************************/
220
/*                     OGR2SQLITEGetPotentialLayerNames()               */
221
/************************************************************************/
222
223
static void OGR2SQLITEGetPotentialLayerNamesInternal(
224
    const char **ppszSQLCommand, std::set<LayerDesc> &oSetLayers,
225
    std::set<CPLString> &oSetSpatialIndex, CPLString &osModifiedSQL, int &nNum)
226
0
{
227
0
    const char *pszSQLCommand = *ppszSQLCommand;
228
0
    const char *pszStart = pszSQLCommand;
229
0
    char ch = '\0';
230
0
    int nParenthesisLevel = 0;
231
0
    bool bLookforFTableName = false;
232
233
0
    while ((ch = *pszSQLCommand) != '\0')
234
0
    {
235
0
        if (ch == '(')
236
0
            nParenthesisLevel++;
237
0
        else if (ch == ')')
238
0
        {
239
0
            nParenthesisLevel--;
240
0
            if (nParenthesisLevel < 0)
241
0
            {
242
0
                pszSQLCommand++;
243
0
                break;
244
0
            }
245
0
        }
246
247
        /* Skip literals and strings */
248
0
        if (ch == '\'' || ch == '"')
249
0
        {
250
0
            char chEscapeChar = ch;
251
0
            pszSQLCommand++;
252
0
            while ((ch = *pszSQLCommand) != '\0')
253
0
            {
254
0
                if (ch == chEscapeChar && pszSQLCommand[1] == chEscapeChar)
255
0
                    pszSQLCommand++;
256
0
                else if (ch == chEscapeChar)
257
0
                {
258
0
                    pszSQLCommand++;
259
0
                    break;
260
0
                }
261
0
                pszSQLCommand++;
262
0
            }
263
0
        }
264
265
0
        else if (STARTS_WITH_CI(pszSQLCommand, "ogr_layer_"))
266
0
        {
267
0
            while (*pszSQLCommand != '\0' && *pszSQLCommand != '(')
268
0
                pszSQLCommand++;
269
270
0
            if (*pszSQLCommand != '(')
271
0
                break;
272
273
0
            pszSQLCommand++;
274
0
            nParenthesisLevel++;
275
276
0
            while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
277
0
                pszSQLCommand++;
278
279
0
            OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand, oSetLayers,
280
0
                               osModifiedSQL);
281
0
        }
282
283
0
        else if (bLookforFTableName &&
284
0
                 STARTS_WITH_CI(pszSQLCommand, "f_table_name") &&
285
0
                 (pszSQLCommand[strlen("f_table_name")] == '=' ||
286
0
                  isspace(static_cast<unsigned char>(
287
0
                      pszSQLCommand[strlen("f_table_name")]))))
288
0
        {
289
0
            pszSQLCommand += strlen("f_table_name");
290
291
0
            while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
292
0
                pszSQLCommand++;
293
294
0
            if (*pszSQLCommand == '=')
295
0
            {
296
0
                pszSQLCommand++;
297
298
0
                while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
299
0
                    pszSQLCommand++;
300
301
0
                oSetSpatialIndex.insert(
302
0
                    OGR2SQLITEExtractUnquotedString(&pszSQLCommand));
303
0
            }
304
305
0
            bLookforFTableName = false;
306
0
        }
307
308
0
        else if (STARTS_WITH_CI(pszSQLCommand, "FROM") &&
309
0
                 isspace(
310
0
                     static_cast<unsigned char>(pszSQLCommand[strlen("FROM")])))
311
0
        {
312
0
            pszSQLCommand += strlen("FROM") + 1;
313
314
0
            while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
315
0
                pszSQLCommand++;
316
317
0
            if (STARTS_WITH_CI(pszSQLCommand, "SpatialIndex") &&
318
0
                isspace(static_cast<unsigned char>(
319
0
                    pszSQLCommand[strlen("SpatialIndex")])))
320
0
            {
321
0
                pszSQLCommand += strlen("SpatialIndex") + 1;
322
323
0
                bLookforFTableName = true;
324
325
0
                continue;
326
0
            }
327
328
0
            if (*pszSQLCommand == '(')
329
0
            {
330
0
                pszSQLCommand++;
331
332
0
                CPLString osTruncated(pszStart);
333
0
                osTruncated.resize(pszSQLCommand - pszStart);
334
0
                osModifiedSQL += osTruncated;
335
336
0
                OGR2SQLITEGetPotentialLayerNamesInternal(
337
0
                    &pszSQLCommand, oSetLayers, oSetSpatialIndex, osModifiedSQL,
338
0
                    nNum);
339
340
0
                pszStart = pszSQLCommand;
341
0
            }
342
0
            else
343
0
                OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand, oSetLayers,
344
0
                                   osModifiedSQL);
345
346
0
            while (*pszSQLCommand != '\0')
347
0
            {
348
0
                if (isspace(static_cast<unsigned char>(*pszSQLCommand)))
349
0
                {
350
0
                    pszSQLCommand++;
351
0
                    while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
352
0
                        pszSQLCommand++;
353
354
0
                    if (STARTS_WITH_CI(pszSQLCommand, "AS"))
355
0
                    {
356
0
                        pszSQLCommand += 2;
357
0
                        while (
358
0
                            isspace(static_cast<unsigned char>(*pszSQLCommand)))
359
0
                            pszSQLCommand++;
360
0
                    }
361
362
                    /* Skip alias */
363
0
                    if (*pszSQLCommand != '\0' && *pszSQLCommand != ',')
364
0
                    {
365
0
                        if (StartsAsSQLITEKeyWord(pszSQLCommand))
366
0
                            break;
367
0
                        OGR2SQLITEExtractUnquotedString(&pszSQLCommand);
368
0
                    }
369
0
                }
370
0
                else if (*pszSQLCommand == ',')
371
0
                {
372
0
                    pszSQLCommand++;
373
0
                    while (isspace(static_cast<unsigned char>(*pszSQLCommand)))
374
0
                        pszSQLCommand++;
375
376
0
                    if (*pszSQLCommand == '(')
377
0
                    {
378
0
                        pszSQLCommand++;
379
380
0
                        CPLString osTruncated(pszStart);
381
0
                        osTruncated.resize(pszSQLCommand - pszStart);
382
0
                        osModifiedSQL += osTruncated;
383
384
0
                        OGR2SQLITEGetPotentialLayerNamesInternal(
385
0
                            &pszSQLCommand, oSetLayers, oSetSpatialIndex,
386
0
                            osModifiedSQL, nNum);
387
388
0
                        pszStart = pszSQLCommand;
389
0
                    }
390
0
                    else
391
0
                        OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand,
392
0
                                           oSetLayers, osModifiedSQL);
393
0
                }
394
0
                else
395
0
                    break;
396
0
            }
397
0
        }
398
0
        else if (STARTS_WITH_CI(pszSQLCommand, "JOIN") &&
399
0
                 isspace(
400
0
                     static_cast<unsigned char>(pszSQLCommand[strlen("JOIN")])))
401
0
        {
402
0
            pszSQLCommand += strlen("JOIN") + 1;
403
0
            OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand, oSetLayers,
404
0
                               osModifiedSQL);
405
0
        }
406
0
        else if (STARTS_WITH_CI(pszSQLCommand, "INTO") &&
407
0
                 isspace(
408
0
                     static_cast<unsigned char>(pszSQLCommand[strlen("INTO")])))
409
0
        {
410
0
            pszSQLCommand += strlen("INTO") + 1;
411
0
            OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand, oSetLayers,
412
0
                               osModifiedSQL);
413
0
        }
414
0
        else if (STARTS_WITH_CI(pszSQLCommand, "UPDATE") &&
415
0
                 isspace(static_cast<unsigned char>(
416
0
                     pszSQLCommand[strlen("UPDATE")])))
417
0
        {
418
0
            pszSQLCommand += strlen("UPDATE") + 1;
419
0
            OGR2SQLITEAddLayer(pszStart, nNum, pszSQLCommand, oSetLayers,
420
0
                               osModifiedSQL);
421
0
        }
422
0
        else
423
0
            pszSQLCommand++;
424
0
    }
425
426
0
    CPLString osTruncated(pszStart);
427
0
    osTruncated.resize(pszSQLCommand - pszStart);
428
0
    osModifiedSQL += osTruncated;
429
430
0
    *ppszSQLCommand = pszSQLCommand;
431
0
}
432
433
static void OGR2SQLITEGetPotentialLayerNames(
434
    const char *pszSQLCommand, std::set<LayerDesc> &oSetLayers,
435
    std::set<CPLString> &oSetSpatialIndex, CPLString &osModifiedSQL)
436
0
{
437
0
    int nNum = 1;
438
0
    OGR2SQLITEGetPotentialLayerNamesInternal(
439
0
        &pszSQLCommand, oSetLayers, oSetSpatialIndex, osModifiedSQL, nNum);
440
0
}
441
442
/************************************************************************/
443
/*                   OGRSQLiteGetReferencedLayers()                     */
444
/************************************************************************/
445
446
std::set<LayerDesc> OGRSQLiteGetReferencedLayers(const char *pszStatement)
447
0
{
448
    /* -------------------------------------------------------------------- */
449
    /*      Analyze the statement to determine which tables will be used.   */
450
    /* -------------------------------------------------------------------- */
451
0
    std::set<LayerDesc> oSetLayers;
452
0
    std::set<CPLString> oSetSpatialIndex;
453
0
    CPLString osModifiedSQL;
454
0
    OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers, oSetSpatialIndex,
455
0
                                     osModifiedSQL);
456
457
0
    return oSetLayers;
458
0
}
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
OGRSQLiteExecuteSQLLayer::OGRSQLiteExecuteSQLLayer(
499
    char *pszTmpDBNameIn, OGRSQLiteDataSource *poDSIn, const CPLString &osSQL,
500
    sqlite3_stmt *hStmtIn, bool bUseStatementForGetNextFeature,
501
    bool bEmptyLayer, bool bCanReopenBaseDS, bool bStringsAsUTF8)
502
0
    : OGRSQLiteSelectLayer(poDSIn, osSQL, hStmtIn,
503
0
                           bUseStatementForGetNextFeature, bEmptyLayer, true,
504
0
                           bCanReopenBaseDS),
505
0
      m_pszTmpDBName(pszTmpDBNameIn), m_bStringsAsUTF8(bStringsAsUTF8)
506
0
{
507
0
}
508
509
/************************************************************************/
510
/*                        ~OGRSQLiteExecuteSQLLayer()                   */
511
/************************************************************************/
512
513
OGRSQLiteExecuteSQLLayer::~OGRSQLiteExecuteSQLLayer()
514
0
{
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
0
    Finalize();
520
521
0
    delete m_poDS;
522
0
    VSIUnlink(m_pszTmpDBName);
523
0
    CPLFree(m_pszTmpDBName);
524
0
}
525
526
/************************************************************************/
527
/*                           TestCapability()                           */
528
/************************************************************************/
529
530
int OGRSQLiteExecuteSQLLayer::TestCapability(const char *pszCap)
531
0
{
532
0
    if (EQUAL(pszCap, OLCStringsAsUTF8))
533
0
        return m_bStringsAsUTF8;
534
0
    return OGRSQLiteSelectLayer::TestCapability(pszCap);
535
0
}
536
537
/************************************************************************/
538
/*               OGR2SQLITE_IgnoreAllFieldsExceptGeometry()             */
539
/************************************************************************/
540
541
#ifdef HAVE_SPATIALITE
542
static void OGR2SQLITE_IgnoreAllFieldsExceptGeometry(OGRLayer *poLayer)
543
{
544
    char **papszIgnored = nullptr;
545
    papszIgnored = CSLAddString(papszIgnored, "OGR_STYLE");
546
    OGRFeatureDefn *poFeatureDefn = poLayer->GetLayerDefn();
547
    for (int i = 0; i < poFeatureDefn->GetFieldCount(); i++)
548
    {
549
        papszIgnored = CSLAddString(
550
            papszIgnored, poFeatureDefn->GetFieldDefn(i)->GetNameRef());
551
    }
552
    poLayer->SetIgnoredFields(const_cast<const char **>(papszIgnored));
553
    CSLDestroy(papszIgnored);
554
}
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
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
0
{
572
0
    OGRGeomFieldDefn *poGeomField =
573
0
        poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomCol);
574
0
    CPLString osGeomColRaw;
575
0
    if (iGeomCol == 0)
576
0
        osGeomColRaw = OGR2SQLITE_GetNameForGeometryColumn(poLayer);
577
0
    else
578
0
        osGeomColRaw = poGeomField->GetNameRef();
579
0
    const char *pszGeomColRaw = osGeomColRaw.c_str();
580
581
0
    CPLString osGeomColEscaped(SQLEscapeLiteral(pszGeomColRaw));
582
0
    const char *pszGeomColEscaped = osGeomColEscaped.c_str();
583
584
0
    CPLString osLayerNameEscaped(SQLEscapeLiteral(osTableName));
585
0
    const char *pszLayerNameEscaped = osLayerNameEscaped.c_str();
586
587
0
    CPLString osIdxNameRaw(
588
0
        CPLSPrintf("idx_%s_%s", oLayerDesc.osLayerName.c_str(), pszGeomColRaw));
589
0
    CPLString osIdxNameEscaped(SQLEscapeName(osIdxNameRaw));
590
591
    /* Make sure that the SRS is injected in spatial_ref_sys */
592
0
    const OGRSpatialReference *poSRS = poGeomField->GetSpatialRef();
593
0
    if (iGeomCol == 0 && poSRS == nullptr)
594
0
        poSRS = poLayer->GetSpatialRef();
595
0
    int nSRSId = poSQLiteDS->GetUndefinedSRID();
596
0
    if (poSRS != nullptr)
597
0
        nSRSId = poSQLiteDS->FetchSRSId(poSRS);
598
599
0
    CPLString osSQL;
600
#ifdef HAVE_SPATIALITE
601
    bool bCreateSpatialIndex = false;
602
#endif
603
0
    if (!bSpatialiteDB)
604
0
    {
605
0
        osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
606
0
                     "f_geometry_column, geometry_format, geometry_type, "
607
0
                     "coord_dimension, srid) "
608
0
                     "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)",
609
0
                     pszLayerNameEscaped, pszGeomColEscaped,
610
0
                     static_cast<int>(wkbFlatten(poLayer->GetGeomType())),
611
0
                     wkbHasZ(poLayer->GetGeomType()) ? 3 : 2, nSRSId);
612
0
    }
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
        std::set<LayerDesc>::const_iterator oIter2 = oSetLayers.begin();
625
        for (; oIter2 != oSetLayers.end(); ++oIter2)
626
        {
627
            const LayerDesc &oLayerDescIter = *oIter2;
628
            if (EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw))
629
            {
630
                bCreateSpatialIndex = true;
631
                break;
632
            }
633
        }
634
635
        /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name =
636
         * 'layername' */
637
        if (!bCreateSpatialIndex)
638
        {
639
            std::set<CPLString>::const_iterator oIter3 =
640
                oSetSpatialIndex.begin();
641
            for (; oIter3 != oSetSpatialIndex.end(); ++oIter3)
642
            {
643
                const CPLString &osNameIter = *oIter3;
644
                if (EQUAL(osNameIter, oLayerDesc.osLayerName))
645
                {
646
                    bCreateSpatialIndex = true;
647
                    break;
648
                }
649
            }
650
        }
651
652
        if (poSQLiteDS->HasSpatialite4Layout())
653
        {
654
            const auto eGeomType = poLayer->GetGeomType();
655
            int nGeomType = eGeomType;
656
            int nCoordDimension = 2;
657
            if (wkbHasZ(eGeomType))
658
            {
659
                nGeomType += 1000;
660
                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
                         static_cast<int>(bCreateSpatialIndex));
670
        }
671
        else
672
        {
673
            const char *pszGeometryType =
674
                OGRToOGCGeomType(poLayer->GetGeomType());
675
            if (pszGeometryType[0] == '\0')
676
                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
                         wkbHasZ(poLayer->GetGeomType()) ? "XYZ" : "XY", nSRSId,
685
                         static_cast<int>(bCreateSpatialIndex));
686
        }
687
    }
688
#endif  // HAVE_SPATIALITE
689
0
    char *pszErrMsg = nullptr;
690
0
    int rc = sqlite3_exec(hDB, osSQL.c_str(), nullptr, nullptr, &pszErrMsg);
691
0
    if (pszErrMsg != nullptr)
692
0
    {
693
0
        CPLDebug("SQLITE", "%s -> %s", osSQL.c_str(), pszErrMsg);
694
0
        sqlite3_free(pszErrMsg);
695
0
    }
696
697
#ifdef HAVE_SPATIALITE
698
    /* -------------------------------------------------------------------- */
699
    /*      Should we create a spatial index ?.                             */
700
    /* -------------------------------------------------------------------- */
701
    if (!bSpatialiteDB || !bCreateSpatialIndex)
702
        return rc == SQLITE_OK;
703
704
    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
    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
                 osIdxNameEscaped.c_str());
726
727
    if (rc == SQLITE_OK)
728
        rc = sqlite3_exec(hDB, osSQL.c_str(), nullptr, nullptr, nullptr);
729
730
    sqlite3_stmt *hStmt = nullptr;
731
    if (rc == SQLITE_OK)
732
    {
733
        const char *pszInsertInto =
734
            CPLSPrintf("INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) "
735
                       "VALUES (?,?,?,?,?)",
736
                       osIdxNameEscaped.c_str());
737
        rc = sqlite3_prepare_v2(hDB, pszInsertInto, -1, &hStmt, nullptr);
738
    }
739
740
    OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer);
741
    poLayer->ResetReading();
742
743
    OGRFeature *poFeature = nullptr;
744
    OGREnvelope sEnvelope;
745
    while (rc == SQLITE_OK &&
746
           (poFeature = poLayer->GetNextFeature()) != nullptr)
747
    {
748
        OGRGeometry *poGeom = poFeature->GetGeometryRef();
749
        if (poGeom != nullptr && !poGeom->IsEmpty())
750
        {
751
            poGeom->getEnvelope(&sEnvelope);
752
            sqlite3_bind_int64(hStmt, 1,
753
                               static_cast<sqlite3_int64>(poFeature->GetFID()));
754
            sqlite3_bind_double(hStmt, 2, sEnvelope.MinX);
755
            sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX);
756
            sqlite3_bind_double(hStmt, 4, sEnvelope.MinY);
757
            sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY);
758
            rc = sqlite3_step(hStmt);
759
            if (rc == SQLITE_OK || rc == SQLITE_DONE)
760
                rc = sqlite3_reset(hStmt);
761
        }
762
        delete poFeature;
763
    }
764
765
    poLayer->SetIgnoredFields(nullptr);
766
767
    sqlite3_finalize(hStmt);
768
769
    if (rc == SQLITE_OK)
770
        rc = sqlite3_exec(hDB, "COMMIT", nullptr, nullptr, nullptr);
771
    else
772
    {
773
        CPLDebug("SQLITE", "Error occurred during spatial index creation : %s",
774
                 sqlite3_errmsg(hDB));
775
        rc = sqlite3_exec(hDB, "ROLLBACK", nullptr, nullptr, nullptr);
776
    }
777
#endif  //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
778
779
#endif  // HAVE_SPATIALITE
780
781
0
    return rc == SQLITE_OK;
782
0
}
783
784
/************************************************************************/
785
/*                          OGRSQLiteExecuteSQL()                       */
786
/************************************************************************/
787
788
OGRLayer *OGRSQLiteExecuteSQL(GDALDataset *poDS, const char *pszStatement,
789
                              OGRGeometry *poSpatialFilter,
790
                              CPL_UNUSED const char *pszDialect)
791
0
{
792
0
    while (*pszStatement != '\0' &&
793
0
           isspace(static_cast<unsigned char>(*pszStatement)))
794
0
        pszStatement++;
795
796
0
    if (STARTS_WITH_CI(pszStatement, "ALTER TABLE ") ||
797
0
        STARTS_WITH_CI(pszStatement, "DROP TABLE ") ||
798
0
        STARTS_WITH_CI(pszStatement, "CREATE INDEX ") ||
799
0
        STARTS_WITH_CI(pszStatement, "DROP INDEX "))
800
0
    {
801
0
        CPLError(CE_Failure, CPLE_NotSupported,
802
0
                 "SQL command not supported with SQLite dialect. "
803
0
                 "Use OGRSQL dialect instead.");
804
0
        return nullptr;
805
0
    }
806
0
    else if (STARTS_WITH_CI(pszStatement, "CREATE VIRTUAL TABLE ") &&
807
0
             CPLTestBool(CPLGetConfigOption(
808
0
                 "OGR_SQLITE_DIALECT_ALLOW_CREATE_VIRTUAL_TABLE", "NO")))
809
0
    {
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
0
    }
816
0
    else
817
0
    {
818
0
        bool bUnderstoodStatement = false;
819
0
        for (const char *pszKeyword : {"SELECT", "WITH", "EXPLAIN", "INSERT",
820
0
                                       "UPDATE", "DELETE", "REPLACE"})
821
0
        {
822
0
            if (STARTS_WITH_CI(pszStatement, pszKeyword) &&
823
0
                std::isspace(static_cast<unsigned char>(
824
0
                    pszStatement[strlen(pszKeyword)])))
825
0
            {
826
0
                bUnderstoodStatement = true;
827
0
                break;
828
0
            }
829
0
        }
830
0
        if (!bUnderstoodStatement)
831
0
        {
832
0
            CPLError(CE_Failure, CPLE_NotSupported, "Unsupported SQL command.");
833
0
            return nullptr;
834
0
        }
835
0
    }
836
837
0
    char *pszTmpDBName = static_cast<char *>(CPLMalloc(256));
838
0
    snprintf(pszTmpDBName, 256, "%s", VSIMemGenerateHiddenFilename("temp.db"));
839
840
0
    OGRSQLiteDataSource *poSQLiteDS = nullptr;
841
0
    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
        CPLMutexHolder oMutexHolder(&hMutex);
860
        static bool bTried = false;
861
        if (!bTried && CPLTestBool(CPLGetConfigOption(
862
                           "OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")))
863
        {
864
            bTried = true;
865
            char *pszCachedFilename = static_cast<char *>(CPLMalloc(256));
866
            snprintf(pszCachedFilename, 256, "%s",
867
                     VSIMemGenerateHiddenFilename("reference.db"));
868
            char **papszOptions = CSLAddString(nullptr, "SPATIALITE=YES");
869
            OGRSQLiteDataSource *poCachedDS = new OGRSQLiteDataSource();
870
            const int nRet =
871
                poCachedDS->Create(pszCachedFilename, papszOptions);
872
            CSLDestroy(papszOptions);
873
            papszOptions = nullptr;
874
            delete poCachedDS;
875
            if (nRet)
876
            {
877
                /* Note: the reference file keeps the ownership of the data, so
878
                 * that */
879
                /* it gets released with VSICleanupFileManager() */
880
                vsi_l_offset nEmptyDBSizeLarge = 0;
881
                pabyEmptyDB = VSIGetMemFileBuffer(pszCachedFilename,
882
                                                  &nEmptyDBSizeLarge, FALSE);
883
                nEmptyDBSize = static_cast<size_t>(nEmptyDBSizeLarge);
884
            }
885
            CPLFree(pszCachedFilename);
886
        }
887
    }
888
889
    /* The following configuration option is useful mostly for debugging/testing
890
     */
891
    if (pabyEmptyDB != nullptr &&
892
        CPLTestBool(
893
            CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")))
894
    {
895
        GByte *pabyEmptyDBClone =
896
            static_cast<GByte *>(VSI_MALLOC_VERBOSE(nEmptyDBSize));
897
        if (pabyEmptyDBClone == nullptr)
898
        {
899
            CPLFree(pszTmpDBName);
900
            return nullptr;
901
        }
902
        memcpy(pabyEmptyDBClone, pabyEmptyDB, nEmptyDBSize);
903
        VSIFCloseL(VSIFileFromMemBuffer(pszTmpDBName, pabyEmptyDBClone,
904
                                        nEmptyDBSize, TRUE));
905
906
        poSQLiteDS = new OGRSQLiteDataSource();
907
        GDALOpenInfo oOpenInfo(pszTmpDBName, GDAL_OF_VECTOR | GDAL_OF_UPDATE);
908
        CPLConfigOptionSetter oSetter("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO",
909
                                      false);
910
        const int nRet = poSQLiteDS->Open(&oOpenInfo);
911
        if (!nRet)
912
        {
913
            /* should not happen really ! */
914
            delete poSQLiteDS;
915
            VSIUnlink(pszTmpDBName);
916
            CPLFree(pszTmpDBName);
917
            return nullptr;
918
        }
919
        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
        delete poSQLiteDS;
941
        poSQLiteDS = nullptr;
942
#else   // HAVE_SPATIALITE
943
0
    if (true)
944
0
    {
945
0
#endif  // HAVE_SPATIALITE
946
947
        // cppcheck-suppress redundantAssignment
948
0
        poSQLiteDS = new OGRSQLiteDataSource();
949
0
        CPLConfigOptionSetter oSetter("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO",
950
0
                                      false);
951
0
        const int nRet = poSQLiteDS->Create(pszTmpDBName, nullptr);
952
0
        if (!nRet)
953
0
        {
954
0
            delete poSQLiteDS;
955
0
            VSIUnlink(pszTmpDBName);
956
0
            CPLFree(pszTmpDBName);
957
0
            return nullptr;
958
0
        }
959
0
    }
960
961
    /* -------------------------------------------------------------------- */
962
    /*      Attach the Virtual Table OGR2SQLITE module to it.               */
963
    /* -------------------------------------------------------------------- */
964
0
    OGR2SQLITEModule *poModule = OGR2SQLITE_Setup(poDS, poSQLiteDS);
965
0
    if (!poModule)
966
0
    {
967
0
        delete poSQLiteDS;
968
0
        VSIUnlink(pszTmpDBName);
969
0
        CPLFree(pszTmpDBName);
970
0
        return nullptr;
971
0
    }
972
0
    sqlite3 *hDB = poSQLiteDS->GetDB();
973
974
    /* -------------------------------------------------------------------- */
975
    /*      Analysze the statement to determine which tables will be used.  */
976
    /* -------------------------------------------------------------------- */
977
0
    std::set<LayerDesc> oSetLayers;
978
0
    std::set<CPLString> oSetSpatialIndex;
979
0
    CPLString osModifiedSQL;
980
0
    OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers, oSetSpatialIndex,
981
0
                                     osModifiedSQL);
982
0
    std::set<LayerDesc>::iterator oIter = oSetLayers.begin();
983
984
0
    if (strcmp(pszStatement, osModifiedSQL.c_str()) != 0)
985
0
        CPLDebug("OGR", "Modified SQL: %s", osModifiedSQL.c_str());
986
0
    pszStatement = osModifiedSQL.c_str(); /* do not use it anymore */
987
988
0
    const bool bFoundOGRStyle =
989
0
        (osModifiedSQL.ifind("OGR_STYLE") != std::string::npos);
990
991
    /* -------------------------------------------------------------------- */
992
    /*      For each of those tables, create a Virtual Table.               */
993
    /* -------------------------------------------------------------------- */
994
0
    OGRLayer *poSingleSrcLayer = nullptr;
995
0
    bool bStringsAsUTF8 = true;
996
0
    for (; oIter != oSetLayers.end(); ++oIter)
997
0
    {
998
0
        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
0
        CPLString osSQL;
1006
0
        OGRLayer *poLayer = nullptr;
1007
0
        CPLString osTableName;
1008
0
        int nExtraDS = -1;
1009
0
        if (oLayerDesc.osDSName.empty())
1010
0
        {
1011
0
            poLayer = poDS->GetLayerByName(oLayerDesc.osLayerName);
1012
            /* Might be a false positive (unlikely) */
1013
0
            if (poLayer == nullptr)
1014
0
                continue;
1015
1016
0
            osTableName = oLayerDesc.osLayerName;
1017
0
        }
1018
0
        else
1019
0
        {
1020
0
            auto poOtherDS = std::unique_ptr<GDALDataset>(
1021
0
                GDALDataset::Open(oLayerDesc.osDSName, GDAL_OF_VECTOR, nullptr,
1022
0
                                  nullptr, nullptr));
1023
0
            if (poOtherDS == nullptr)
1024
0
            {
1025
0
                CPLError(CE_Failure, CPLE_AppDefined,
1026
0
                         "Cannot open datasource '%s'",
1027
0
                         oLayerDesc.osDSName.c_str());
1028
0
                delete poSQLiteDS;
1029
0
                VSIUnlink(pszTmpDBName);
1030
0
                CPLFree(pszTmpDBName);
1031
0
                return nullptr;
1032
0
            }
1033
1034
0
            poLayer = poOtherDS->GetLayerByName(oLayerDesc.osLayerName);
1035
0
            if (poLayer == nullptr)
1036
0
            {
1037
0
                CPLError(CE_Failure, CPLE_AppDefined,
1038
0
                         "Cannot find layer '%s' in '%s'",
1039
0
                         oLayerDesc.osLayerName.c_str(),
1040
0
                         oLayerDesc.osDSName.c_str());
1041
0
                delete poSQLiteDS;
1042
0
                VSIUnlink(pszTmpDBName);
1043
0
                CPLFree(pszTmpDBName);
1044
0
                return nullptr;
1045
0
            }
1046
1047
0
            osTableName = oLayerDesc.osSubstitutedName;
1048
1049
0
            nExtraDS = OGR2SQLITE_AddExtraDS(poModule, poOtherDS.release());
1050
0
        }
1051
1052
0
        if (!poLayer->TestCapability(OLCStringsAsUTF8))
1053
0
            bStringsAsUTF8 = false;
1054
1055
0
        if (oSetLayers.size() == 1)
1056
0
            poSingleSrcLayer = poLayer;
1057
1058
0
        osSQL.Printf(
1059
0
            "CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d,%d)",
1060
0
            SQLEscapeName(osTableName).c_str(), nExtraDS,
1061
0
            SQLEscapeLiteral(oLayerDesc.osLayerName).c_str(),
1062
0
            bFoundOGRStyle ? 1 : 0, TRUE /*bExposeOGRNativeData*/);
1063
1064
0
        char *pszErrMsg = nullptr;
1065
0
        int rc = sqlite3_exec(hDB, osSQL.c_str(), nullptr, nullptr, &pszErrMsg);
1066
0
        if (rc != SQLITE_OK)
1067
0
        {
1068
0
            CPLError(CE_Failure, CPLE_AppDefined,
1069
0
                     "Cannot create virtual table for layer '%s' : %s",
1070
0
                     osTableName.c_str(), pszErrMsg);
1071
0
            sqlite3_free(pszErrMsg);
1072
0
            continue;
1073
0
        }
1074
1075
0
        for (int i = 0; i < poLayer->GetLayerDefn()->GetGeomFieldCount(); i++)
1076
0
        {
1077
0
            OGR2SQLITEDealWithSpatialColumn(poLayer, i, oLayerDesc, osTableName,
1078
0
                                            poSQLiteDS, hDB, bSpatialiteDB,
1079
0
                                            oSetLayers, oSetSpatialIndex);
1080
0
        }
1081
0
    }
1082
1083
    /* -------------------------------------------------------------------- */
1084
    /*      Reload, so that virtual tables are recognized                   */
1085
    /* -------------------------------------------------------------------- */
1086
0
    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
0
    bool bUseStatementForGetNextFeature = true;
1095
0
    bool bEmptyLayer = false;
1096
1097
0
    sqlite3_stmt *hSQLStmt = nullptr;
1098
0
    int rc = sqlite3_prepare_v2(hDB, pszStatement, -1, &hSQLStmt, nullptr);
1099
1100
0
    if (rc != SQLITE_OK)
1101
0
    {
1102
0
        CPLError(CE_Failure, CPLE_AppDefined,
1103
0
                 "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n  %s", pszStatement,
1104
0
                 sqlite3_errmsg(hDB));
1105
1106
0
        if (hSQLStmt != nullptr)
1107
0
        {
1108
0
            sqlite3_finalize(hSQLStmt);
1109
0
        }
1110
1111
0
        delete poSQLiteDS;
1112
0
        VSIUnlink(pszTmpDBName);
1113
0
        CPLFree(pszTmpDBName);
1114
1115
0
        return nullptr;
1116
0
    }
1117
1118
    /* -------------------------------------------------------------------- */
1119
    /*      Do we get a resultset?                                          */
1120
    /* -------------------------------------------------------------------- */
1121
0
    rc = sqlite3_step(hSQLStmt);
1122
0
    if (rc != SQLITE_ROW)
1123
0
    {
1124
0
        if (rc != SQLITE_DONE)
1125
0
        {
1126
0
            CPLError(CE_Failure, CPLE_AppDefined,
1127
0
                     "In ExecuteSQL(): sqlite3_step(%s):\n  %s", pszStatement,
1128
0
                     sqlite3_errmsg(hDB));
1129
1130
0
            sqlite3_finalize(hSQLStmt);
1131
1132
0
            delete poSQLiteDS;
1133
0
            VSIUnlink(pszTmpDBName);
1134
0
            CPLFree(pszTmpDBName);
1135
1136
0
            return nullptr;
1137
0
        }
1138
1139
0
        if (!STARTS_WITH_CI(pszStatement, "SELECT "))
1140
0
        {
1141
1142
0
            sqlite3_finalize(hSQLStmt);
1143
1144
0
            delete poSQLiteDS;
1145
0
            VSIUnlink(pszTmpDBName);
1146
0
            CPLFree(pszTmpDBName);
1147
1148
0
            return nullptr;
1149
0
        }
1150
1151
0
        bUseStatementForGetNextFeature = false;
1152
0
        bEmptyLayer = true;
1153
0
    }
1154
1155
    /* -------------------------------------------------------------------- */
1156
    /*      Create layer.                                                   */
1157
    /* -------------------------------------------------------------------- */
1158
1159
0
    auto poDrv = poDS->GetDriver();
1160
0
    const bool bCanReopenBaseDS =
1161
0
        !(poDrv && (EQUAL(poDrv->GetDescription(), "MEM") ||
1162
0
                    EQUAL(poDrv->GetDescription(), "Memory")));
1163
0
    OGRSQLiteSelectLayer *poLayer = new OGRSQLiteExecuteSQLLayer(
1164
0
        pszTmpDBName, poSQLiteDS, pszStatement, hSQLStmt,
1165
0
        bUseStatementForGetNextFeature, bEmptyLayer, bCanReopenBaseDS,
1166
0
        bStringsAsUTF8);
1167
1168
0
    if (poSpatialFilter != nullptr)
1169
0
    {
1170
0
        const auto nErrorCounter = CPLGetErrorCounter();
1171
0
        poLayer->SetSpatialFilter(0, poSpatialFilter);
1172
0
        if (CPLGetErrorCounter() > nErrorCounter &&
1173
0
            CPLGetLastErrorType() != CE_None)
1174
0
        {
1175
0
            delete poLayer;
1176
0
            return nullptr;
1177
0
        }
1178
0
    }
1179
1180
0
    if (poSingleSrcLayer != nullptr)
1181
0
        poLayer->SetMetadata(poSingleSrcLayer->GetMetadata("NATIVE_DATA"),
1182
0
                             "NATIVE_DATA");
1183
1184
0
    return poLayer;
1185
0
}
1186
1187
#endif  // HAVE_SQLITE3EXT_H