Coverage Report

Created: 2026-04-01 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Implements OGRGenSQLResultsLayer.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2002, Frank Warmerdam
9
 * Copyright (c) 2008-2014, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "ogr_swq.h"
15
#include "ogr_p.h"
16
#include "ogr_gensql.h"
17
#include "cpl_string.h"
18
#include "ogr_api.h"
19
#include "ogr_recordbatch.h"
20
#include "ogrlayerarrow.h"
21
#include "cpl_time.h"
22
#include <algorithm>
23
#include <limits>
24
#include <map>
25
#include <set>
26
#include <vector>
27
28
//! @cond Doxygen_Suppress
29
extern const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];
30
31
class OGRGenSQLGeomFieldDefn final : public OGRGeomFieldDefn
32
{
33
  public:
34
    explicit OGRGenSQLGeomFieldDefn(OGRGeomFieldDefn *poGeomFieldDefn)
35
0
        : OGRGeomFieldDefn(poGeomFieldDefn->GetNameRef(),
36
0
                           poGeomFieldDefn->GetType()),
37
0
          bForceGeomType(FALSE)
38
0
    {
39
0
        SetSpatialRef(poGeomFieldDefn->GetSpatialRef());
40
0
    }
41
42
    ~OGRGenSQLGeomFieldDefn() override;
43
44
    int bForceGeomType;
45
};
46
47
0
OGRGenSQLGeomFieldDefn::~OGRGenSQLGeomFieldDefn() = default;
48
49
/************************************************************************/
50
/*                OGRGenSQLResultsLayerHasSpecialField()                */
51
/************************************************************************/
52
53
static bool OGRGenSQLResultsLayerHasSpecialField(swq_expr_node *expr,
54
                                                 int nMinIndexForSpecialField)
55
0
{
56
0
    if (expr->eNodeType == SNT_COLUMN)
57
0
    {
58
0
        if (expr->table_index == 0)
59
0
        {
60
0
            return expr->field_index >= nMinIndexForSpecialField &&
61
0
                   expr->field_index <
62
0
                       nMinIndexForSpecialField + SPECIAL_FIELD_COUNT;
63
0
        }
64
0
    }
65
0
    else if (expr->eNodeType == SNT_OPERATION)
66
0
    {
67
0
        for (int i = 0; i < expr->nSubExprCount; i++)
68
0
        {
69
0
            if (OGRGenSQLResultsLayerHasSpecialField(expr->papoSubExpr[i],
70
0
                                                     nMinIndexForSpecialField))
71
0
                return true;
72
0
        }
73
0
    }
74
0
    return false;
75
0
}
76
77
/************************************************************************/
78
/*                       OGRGenSQLResultsLayer()                        */
79
/************************************************************************/
80
81
OGRGenSQLResultsLayer::OGRGenSQLResultsLayer(
82
    GDALDataset *poSrcDSIn, std::unique_ptr<swq_select> &&pSelectInfo,
83
    const OGRGeometry *poSpatFilter, const char *pszWHEREIn,
84
    const char *pszDialect)
85
0
    : m_poSrcDS(poSrcDSIn), m_pSelectInfo(std::move(pSelectInfo))
86
0
{
87
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
88
89
    /* -------------------------------------------------------------------- */
90
    /*      Identify all the layers involved in the SELECT.                 */
91
    /* -------------------------------------------------------------------- */
92
0
    m_apoTableLayers.reserve(psSelectInfo->table_count);
93
94
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
95
0
    {
96
0
        swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
97
0
        GDALDataset *poTableDS = m_poSrcDS;
98
99
0
        if (psTableDef->data_source != nullptr)
100
0
        {
101
0
            std::unique_ptr<GDALDataset, GDALDatasetUniquePtrReleaser> poNewDS(
102
0
                GDALDataset::Open(psTableDef->data_source,
103
0
                                  GDAL_OF_VECTOR | GDAL_OF_SHARED));
104
0
            if (!poNewDS)
105
0
            {
106
0
                if (strlen(CPLGetLastErrorMsg()) == 0)
107
0
                    CPLError(CE_Failure, CPLE_AppDefined,
108
0
                             "Unable to open secondary datasource\n"
109
0
                             "`%s' required by JOIN.",
110
0
                             psTableDef->data_source);
111
0
                return;
112
0
            }
113
114
0
            m_apoExtraDS.emplace_back(std::move(poNewDS));
115
0
            poTableDS = m_apoExtraDS.back().get();
116
0
        }
117
118
0
        m_apoTableLayers.push_back(
119
0
            poTableDS->GetLayerByName(psTableDef->table_name));
120
0
        if (!m_apoTableLayers.back())
121
0
            return;
122
0
    }
123
124
0
    m_poSrcLayer = m_apoTableLayers[0];
125
0
    SetMetadata(m_poSrcLayer->GetMetadata("NATIVE_DATA"), "NATIVE_DATA");
126
127
    /* -------------------------------------------------------------------- */
128
    /*      If the user has explicitly requested a OGRSQL dialect, then    */
129
    /*      we should avoid to forward the where clause to the source layer */
130
    /*      when there is a risk it cannot understand it (#4022)            */
131
    /* -------------------------------------------------------------------- */
132
0
    m_bForwardWhereToSourceLayer = true;
133
0
    if (pszWHEREIn)
134
0
    {
135
0
        if (psSelectInfo->where_expr && pszDialect != nullptr &&
136
0
            EQUAL(pszDialect, "OGRSQL"))
137
0
        {
138
0
            const int nMinIndexForSpecialField =
139
0
                m_poSrcLayer->GetLayerDefn()->GetFieldCount();
140
0
            m_bForwardWhereToSourceLayer =
141
0
                !OGRGenSQLResultsLayerHasSpecialField(psSelectInfo->where_expr,
142
0
                                                      nMinIndexForSpecialField);
143
0
        }
144
0
        m_osInitialWHERE = pszWHEREIn;
145
0
    }
146
147
    /* -------------------------------------------------------------------- */
148
    /*      Prepare a feature definition based on the query.                */
149
    /* -------------------------------------------------------------------- */
150
0
    OGRFeatureDefn *poSrcDefn = m_poSrcLayer->GetLayerDefn();
151
152
0
    m_poDefn = new OGRFeatureDefn(psSelectInfo->table_defs[0].table_alias);
153
0
    SetDescription(m_poDefn->GetName());
154
0
    m_poDefn->SetGeomType(wkbNone);
155
0
    m_poDefn->Reference();
156
157
0
    m_iFIDFieldIndex = poSrcDefn->GetFieldCount();
158
159
0
    for (std::size_t iField = 0; iField < psSelectInfo->column_defs.size();
160
0
         iField++)
161
0
    {
162
0
        swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
163
0
        OGRFieldDefn oFDefn("", OFTInteger);
164
0
        OGRGeomFieldDefn oGFDefn("", wkbUnknown);
165
0
        OGRFieldDefn *poSrcFDefn = nullptr;
166
0
        OGRGeomFieldDefn *poSrcGFDefn = nullptr;
167
0
        int bIsGeometry = FALSE;
168
0
        OGRFeatureDefn *poLayerDefn = nullptr;
169
0
        int iSrcGeomField = -1;
170
171
0
        if (psColDef->bHidden)
172
0
            continue;
173
174
0
        if (psColDef->table_index != -1)
175
0
            poLayerDefn =
176
0
                m_apoTableLayers[psColDef->table_index]->GetLayerDefn();
177
178
0
        if (psColDef->field_index > -1 && poLayerDefn != nullptr &&
179
0
            psColDef->field_index < poLayerDefn->GetFieldCount())
180
0
        {
181
0
            poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index);
182
0
        }
183
184
0
        if (poLayerDefn != nullptr &&
185
0
            IS_GEOM_FIELD_INDEX(poLayerDefn, psColDef->field_index))
186
0
        {
187
0
            bIsGeometry = TRUE;
188
0
            iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
189
0
                poLayerDefn, psColDef->field_index);
190
0
            poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
191
0
        }
192
193
0
        if (psColDef->target_type == SWQ_GEOMETRY)
194
0
            bIsGeometry = TRUE;
195
196
0
        if (psColDef->col_func == SWQCF_COUNT)
197
0
            bIsGeometry = FALSE;
198
199
0
        if (strlen(psColDef->field_name) == 0 && !bIsGeometry)
200
0
        {
201
0
            CPLFree(psColDef->field_name);
202
0
            psColDef->field_name = static_cast<char *>(CPLMalloc(40));
203
0
            snprintf(psColDef->field_name, 40, "FIELD_%d",
204
0
                     m_poDefn->GetFieldCount() + 1);
205
0
        }
206
207
0
        if (psColDef->field_alias != nullptr)
208
0
        {
209
0
            if (bIsGeometry)
210
0
                oGFDefn.SetName(psColDef->field_alias);
211
0
            else
212
0
                oFDefn.SetName(psColDef->field_alias);
213
0
        }
214
0
        else if (psColDef->col_func != SWQCF_NONE)
215
0
        {
216
0
            const swq_operation *op = swq_op_registrar::GetOperator(
217
0
                static_cast<swq_op>(psColDef->col_func));
218
219
0
            oFDefn.SetName(
220
0
                CPLSPrintf("%s_%s", op->pszName, psColDef->field_name));
221
0
        }
222
0
        else
223
0
        {
224
0
            CPLString osName;
225
0
            if (psColDef->table_name[0])
226
0
            {
227
0
                osName = psColDef->table_name;
228
0
                osName += ".";
229
0
            }
230
0
            osName += psColDef->field_name;
231
232
0
            if (bIsGeometry)
233
0
                oGFDefn.SetName(osName);
234
0
            else
235
0
                oFDefn.SetName(osName);
236
0
        }
237
238
0
        if (psColDef->col_func == SWQCF_COUNT)
239
0
            oFDefn.SetType(OFTInteger64);
240
0
        else if (poSrcFDefn != nullptr)
241
0
        {
242
0
            if (psColDef->col_func == SWQCF_STDDEV_POP ||
243
0
                psColDef->col_func == SWQCF_STDDEV_SAMP)
244
0
            {
245
0
                oFDefn.SetType(OFTReal);
246
0
            }
247
0
            else if (psColDef->col_func != SWQCF_AVG ||
248
0
                     psColDef->field_type == SWQ_DATE ||
249
0
                     psColDef->field_type == SWQ_TIME ||
250
0
                     psColDef->field_type == SWQ_TIMESTAMP)
251
0
            {
252
0
                oFDefn.SetType(poSrcFDefn->GetType());
253
0
                if (psColDef->col_func == SWQCF_NONE ||
254
0
                    psColDef->col_func == SWQCF_MIN ||
255
0
                    psColDef->col_func == SWQCF_MAX)
256
0
                {
257
0
                    oFDefn.SetSubType(poSrcFDefn->GetSubType());
258
0
                }
259
0
            }
260
0
            else
261
0
            {
262
0
                oFDefn.SetType(OFTReal);
263
0
            }
264
265
0
            if (psColDef->col_func != SWQCF_AVG &&
266
0
                psColDef->col_func != SWQCF_STDDEV_POP &&
267
0
                psColDef->col_func != SWQCF_STDDEV_SAMP &&
268
0
                psColDef->col_func != SWQCF_SUM)
269
0
            {
270
0
                oFDefn.SetWidth(poSrcFDefn->GetWidth());
271
0
                oFDefn.SetPrecision(poSrcFDefn->GetPrecision());
272
0
            }
273
274
0
            if (psColDef->col_func == SWQCF_NONE)
275
0
                oFDefn.SetDomainName(poSrcFDefn->GetDomainName());
276
0
        }
277
0
        else if (poSrcGFDefn != nullptr)
278
0
        {
279
0
            oGFDefn.SetType(poSrcGFDefn->GetType());
280
0
            oGFDefn.SetSpatialRef(poSrcGFDefn->GetSpatialRef());
281
0
        }
282
0
        else if (psColDef->field_index >= m_iFIDFieldIndex)
283
0
        {
284
0
            switch (SpecialFieldTypes[psColDef->field_index - m_iFIDFieldIndex])
285
0
            {
286
0
                case SWQ_INTEGER:
287
0
                    oFDefn.SetType(OFTInteger);
288
0
                    break;
289
0
                case SWQ_INTEGER64:
290
0
                    oFDefn.SetType(OFTInteger64);
291
0
                    break;
292
0
                case SWQ_FLOAT:
293
0
                    oFDefn.SetType(OFTReal);
294
0
                    break;
295
0
                default:
296
0
                    oFDefn.SetType(OFTString);
297
0
                    break;
298
0
            }
299
0
            if (psColDef->field_index - m_iFIDFieldIndex == SPF_FID &&
300
0
                m_poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
301
0
                EQUAL(m_poSrcLayer->GetMetadataItem(OLMD_FID64), "YES"))
302
0
            {
303
0
                oFDefn.SetType(OFTInteger64);
304
0
            }
305
0
        }
306
0
        else
307
0
        {
308
0
            switch (psColDef->field_type)
309
0
            {
310
0
                case SWQ_INTEGER:
311
0
                    oFDefn.SetType(OFTInteger);
312
0
                    break;
313
314
0
                case SWQ_INTEGER64:
315
0
                    oFDefn.SetType(OFTInteger64);
316
0
                    break;
317
318
0
                case SWQ_BOOLEAN:
319
0
                    oFDefn.SetType(OFTInteger);
320
0
                    oFDefn.SetSubType(OFSTBoolean);
321
0
                    break;
322
323
0
                case SWQ_FLOAT:
324
0
                    oFDefn.SetType(OFTReal);
325
0
                    break;
326
327
0
                default:
328
0
                    oFDefn.SetType(OFTString);
329
0
                    break;
330
0
            }
331
0
        }
332
333
        /* setting up the target_type */
334
0
        switch (psColDef->target_type)
335
0
        {
336
0
            case SWQ_OTHER:
337
0
                break;
338
0
            case SWQ_INTEGER:
339
0
                oFDefn.SetType(OFTInteger);
340
0
                break;
341
0
            case SWQ_INTEGER64:
342
0
                oFDefn.SetType(OFTInteger64);
343
0
                break;
344
0
            case SWQ_BOOLEAN:
345
0
                oFDefn.SetType(OFTInteger);
346
0
                oFDefn.SetSubType(OFSTBoolean);
347
0
                break;
348
0
            case SWQ_FLOAT:
349
0
                oFDefn.SetType(OFTReal);
350
0
                break;
351
0
            case SWQ_STRING:
352
0
                oFDefn.SetType(OFTString);
353
0
                break;
354
0
            case SWQ_TIMESTAMP:
355
0
                oFDefn.SetType(OFTDateTime);
356
0
                break;
357
0
            case SWQ_DATE:
358
0
                oFDefn.SetType(OFTDate);
359
0
                break;
360
0
            case SWQ_TIME:
361
0
                oFDefn.SetType(OFTTime);
362
0
                break;
363
0
            case SWQ_GEOMETRY:
364
0
                break;
365
366
0
            default:
367
0
                CPLAssert(false);
368
0
                oFDefn.SetType(OFTString);
369
0
                break;
370
0
        }
371
0
        if (psColDef->target_subtype != OFSTNone)
372
0
            oFDefn.SetSubType(psColDef->target_subtype);
373
374
0
        if (psColDef->field_length > 0)
375
0
        {
376
0
            oFDefn.SetWidth(psColDef->field_length);
377
0
        }
378
379
0
        if (psColDef->field_precision >= 0)
380
0
        {
381
0
            oFDefn.SetPrecision(psColDef->field_precision);
382
0
        }
383
384
0
        if (bIsGeometry)
385
0
        {
386
0
            m_anGeomFieldToSrcGeomField.push_back(iSrcGeomField);
387
            /* Hack while drivers haven't been updated so that */
388
            /* poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() ==
389
             * m_poSrcLayer->GetSpatialRef() */
390
0
            if (iSrcGeomField == 0 && poSrcDefn->GetGeomFieldCount() == 1 &&
391
0
                oGFDefn.GetSpatialRef() == nullptr)
392
0
            {
393
0
                oGFDefn.SetSpatialRef(m_poSrcLayer->GetSpatialRef());
394
0
            }
395
0
            int bForceGeomType = FALSE;
396
0
            if (psColDef->eGeomType != wkbUnknown)
397
0
            {
398
0
                oGFDefn.SetType(psColDef->eGeomType);
399
0
                bForceGeomType = TRUE;
400
0
            }
401
0
            if (psColDef->nSRID > 0)
402
0
            {
403
0
                OGRSpatialReference *poSRS = new OGRSpatialReference();
404
0
                poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
405
0
                if (poSRS->importFromEPSG(psColDef->nSRID) == OGRERR_NONE)
406
0
                {
407
0
                    oGFDefn.SetSpatialRef(poSRS);
408
0
                }
409
0
                poSRS->Release();
410
0
            }
411
412
0
            auto poMyGeomFieldDefn =
413
0
                std::make_unique<OGRGenSQLGeomFieldDefn>(&oGFDefn);
414
0
            poMyGeomFieldDefn->bForceGeomType = bForceGeomType;
415
0
            m_poDefn->AddGeomFieldDefn(std::move(poMyGeomFieldDefn));
416
0
        }
417
0
        else
418
0
            m_poDefn->AddFieldDefn(&oFDefn);
419
0
    }
420
421
    /* -------------------------------------------------------------------- */
422
    /*      Add implicit geometry field.                                    */
423
    /* -------------------------------------------------------------------- */
424
0
    if (psSelectInfo->query_mode == SWQM_RECORDSET &&
425
0
        m_poDefn->GetGeomFieldCount() == 0 &&
426
0
        poSrcDefn->GetGeomFieldCount() == 1 && !psSelectInfo->bExcludedGeometry)
427
0
    {
428
0
        psSelectInfo->column_defs.emplace_back();
429
430
0
        swq_col_def *col_def = &psSelectInfo->column_defs.back();
431
432
0
        memset(col_def, 0, sizeof(swq_col_def));
433
0
        const char *pszName = poSrcDefn->GetGeomFieldDefn(0)->GetNameRef();
434
0
        if (*pszName != '\0')
435
0
            col_def->field_name = CPLStrdup(pszName);
436
0
        else
437
0
            col_def->field_name =
438
0
                CPLStrdup(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
439
0
        col_def->field_alias = nullptr;
440
0
        col_def->table_index = 0;
441
0
        col_def->field_index =
442
0
            GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poSrcDefn, 0);
443
0
        col_def->field_type = SWQ_GEOMETRY;
444
0
        col_def->target_type = SWQ_GEOMETRY;
445
446
0
        m_anGeomFieldToSrcGeomField.push_back(0);
447
448
0
        m_poDefn->AddGeomFieldDefn(std::make_unique<OGRGenSQLGeomFieldDefn>(
449
0
            poSrcDefn->GetGeomFieldDefn(0)));
450
451
        /* Hack while drivers haven't been updated so that */
452
        /* poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() ==
453
         * m_poSrcLayer->GetSpatialRef() */
454
0
        if (poSrcDefn->GetGeomFieldDefn(0)->GetSpatialRef() == nullptr)
455
0
        {
456
0
            m_poDefn->GetGeomFieldDefn(0)->SetSpatialRef(
457
0
                m_poSrcLayer->GetSpatialRef());
458
0
        }
459
0
    }
460
461
    /* -------------------------------------------------------------------- */
462
    /*      Now that we have m_poSrcLayer, we can install a spatial filter  */
463
    /*      if there is one.                                                */
464
    /* -------------------------------------------------------------------- */
465
0
    if (poSpatFilter)
466
0
    {
467
0
        if (m_poDefn->GetGeomFieldCount() > 0)
468
0
        {
469
0
            OGRGenSQLResultsLayer::SetSpatialFilter(
470
0
                0, const_cast<OGRGeometry *>(poSpatFilter));
471
0
        }
472
0
        else
473
0
        {
474
0
            m_bSpatialFilterSetOnSourceLayer = true;
475
0
            m_poSrcLayer->SetSpatialFilter(
476
0
                0, const_cast<OGRGeometry *>(poSpatFilter));
477
0
        }
478
0
    }
479
480
0
    OGRGenSQLResultsLayer::ResetReading();
481
482
0
    FindAndSetIgnoredFields();
483
484
0
    if (!m_bForwardWhereToSourceLayer)
485
0
        OGRLayer::SetAttributeFilter(m_osInitialWHERE.c_str());
486
0
}
487
488
/************************************************************************/
489
/*                       ~OGRGenSQLResultsLayer()                       */
490
/************************************************************************/
491
492
OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
493
494
0
{
495
0
    if (m_nFeaturesRead > 0 && m_poDefn != nullptr)
496
0
    {
497
0
        CPLDebug("GenSQL", CPL_FRMT_GIB " features read on layer '%s'.",
498
0
                 m_nFeaturesRead, m_poDefn->GetName());
499
0
    }
500
501
0
    OGRGenSQLResultsLayer::ClearFilters();
502
503
0
    if (m_poDefn != nullptr)
504
0
    {
505
0
        m_poDefn->Release();
506
0
    }
507
0
}
508
509
/************************************************************************/
510
/*                            ClearFilters()                            */
511
/*                                                                      */
512
/*      Clear up all filters currently in place on the target layer,    */
513
/*      and joined layers.  We try not to leave them installed          */
514
/*      except when actively fetching features.                         */
515
/************************************************************************/
516
517
void OGRGenSQLResultsLayer::ClearFilters()
518
519
0
{
520
    /* -------------------------------------------------------------------- */
521
    /*      Clear any filters installed on the target layer.                */
522
    /* -------------------------------------------------------------------- */
523
0
    m_poSrcLayer->ResetReading();
524
0
    m_poSrcLayer->SetAttributeFilter("");
525
0
    if (GetLayerDefn()->GetGeomFieldCount() > 0)
526
0
        m_poSrcLayer->SetSpatialFilter(nullptr);
527
528
    /* -------------------------------------------------------------------- */
529
    /*      Clear any attribute filter installed on the joined layers.      */
530
    /* -------------------------------------------------------------------- */
531
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
532
533
0
    if (psSelectInfo != nullptr)
534
0
    {
535
0
        for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
536
0
        {
537
0
            swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
538
0
            OGRLayer *poJoinLayer =
539
0
                m_apoTableLayers[psJoinInfo->secondary_table];
540
541
0
            poJoinLayer->SetAttributeFilter("");
542
0
        }
543
0
    }
544
545
    /* -------------------------------------------------------------------- */
546
    /*      Clear any ignored field lists installed on source layers        */
547
    /* -------------------------------------------------------------------- */
548
0
    if (psSelectInfo != nullptr)
549
0
    {
550
0
        for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
551
0
        {
552
0
            OGRLayer *poLayer = m_apoTableLayers[iTable];
553
0
            poLayer->SetIgnoredFields(nullptr);
554
0
        }
555
0
    }
556
0
}
557
558
/************************************************************************/
559
/*                 MustEvaluateSpatialFilterOnGenSQL()                  */
560
/************************************************************************/
561
562
int OGRGenSQLResultsLayer::MustEvaluateSpatialFilterOnGenSQL()
563
0
{
564
0
    int bEvaluateSpatialFilter = FALSE;
565
0
    if (m_poFilterGeom != nullptr && m_iGeomFieldFilter >= 0 &&
566
0
        m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount())
567
0
    {
568
0
        int iSrcGeomField = m_anGeomFieldToSrcGeomField[m_iGeomFieldFilter];
569
0
        if (iSrcGeomField < 0)
570
0
            bEvaluateSpatialFilter = TRUE;
571
0
    }
572
0
    return bEvaluateSpatialFilter;
573
0
}
574
575
/************************************************************************/
576
/*                        ApplyFiltersToSource()                        */
577
/************************************************************************/
578
579
void OGRGenSQLResultsLayer::ApplyFiltersToSource()
580
0
{
581
0
    if (m_bForwardWhereToSourceLayer && !m_osInitialWHERE.empty())
582
0
    {
583
0
        m_poSrcLayer->SetAttributeFilter(m_osInitialWHERE.c_str());
584
0
    }
585
0
    else
586
0
    {
587
0
        m_poSrcLayer->SetAttributeFilter(nullptr);
588
0
    }
589
0
    if (m_iGeomFieldFilter >= 0 &&
590
0
        m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount())
591
0
    {
592
0
        int iSrcGeomField = m_anGeomFieldToSrcGeomField[m_iGeomFieldFilter];
593
0
        if (iSrcGeomField >= 0)
594
0
            m_poSrcLayer->SetSpatialFilter(iSrcGeomField, m_poFilterGeom);
595
0
    }
596
597
0
    m_poSrcLayer->ResetReading();
598
0
}
599
600
/************************************************************************/
601
/*                            ResetReading()                            */
602
/************************************************************************/
603
604
void OGRGenSQLResultsLayer::ResetReading()
605
606
0
{
607
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
608
609
0
    if (psSelectInfo->query_mode == SWQM_RECORDSET)
610
0
    {
611
0
        ApplyFiltersToSource();
612
0
    }
613
614
0
    m_nNextIndexFID = psSelectInfo->offset;
615
0
    m_nIteratedFeatures = -1;
616
0
    m_bEOF = false;
617
0
}
618
619
/************************************************************************/
620
/*                           SetNextByIndex()                           */
621
/*                                                                      */
622
/*      If we already have an FID list, we can easily reposition        */
623
/*      ourselves in it.                                                */
624
/************************************************************************/
625
626
OGRErr OGRGenSQLResultsLayer::SetNextByIndex(GIntBig nIndex)
627
628
0
{
629
0
    m_bEOF = false;
630
631
0
    if (nIndex < 0)
632
0
    {
633
0
        m_bEOF = true;
634
0
        return OGRERR_NON_EXISTING_FEATURE;
635
0
    }
636
637
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
638
639
0
    if (psSelectInfo->limit >= 0)
640
0
    {
641
0
        m_nIteratedFeatures = nIndex;
642
0
        if (m_nIteratedFeatures >= psSelectInfo->limit)
643
0
        {
644
0
            return OGRERR_NON_EXISTING_FEATURE;
645
0
        }
646
0
    }
647
648
0
    CreateOrderByIndex();
649
650
0
    if (nIndex > std::numeric_limits<GIntBig>::max() - psSelectInfo->offset)
651
0
    {
652
0
        m_bEOF = true;
653
0
        return OGRERR_NON_EXISTING_FEATURE;
654
0
    }
655
0
    if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD ||
656
0
        psSelectInfo->query_mode == SWQM_DISTINCT_LIST || !m_anFIDIndex.empty())
657
0
    {
658
0
        m_nNextIndexFID = nIndex + psSelectInfo->offset;
659
0
        return OGRERR_NONE;
660
0
    }
661
0
    else
662
0
    {
663
0
        OGRErr eErr =
664
0
            m_poSrcLayer->SetNextByIndex(nIndex + psSelectInfo->offset);
665
0
        if (eErr != OGRERR_NONE)
666
0
            m_bEOF = true;
667
0
        return eErr;
668
0
    }
669
0
}
670
671
/************************************************************************/
672
/*                             IGetExtent()                             */
673
/************************************************************************/
674
675
OGRErr OGRGenSQLResultsLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent,
676
                                         bool bForce)
677
678
0
{
679
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
680
681
0
    if (psSelectInfo->query_mode == SWQM_RECORDSET)
682
0
    {
683
0
        int iSrcGeomField = m_anGeomFieldToSrcGeomField[iGeomField];
684
0
        if (iSrcGeomField >= 0)
685
0
            return m_poSrcLayer->GetExtent(iSrcGeomField, psExtent, bForce);
686
0
        else
687
0
            return OGRLayer::IGetExtent(iGeomField, psExtent, bForce);
688
0
    }
689
0
    else
690
0
        return OGRERR_FAILURE;
691
0
}
692
693
/************************************************************************/
694
/*                          GetFeatureCount()                           */
695
/************************************************************************/
696
697
GIntBig OGRGenSQLResultsLayer::GetFeatureCount(int bForce)
698
699
0
{
700
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
701
702
0
    CreateOrderByIndex();
703
704
0
    GIntBig nRet = 0;
705
0
    if (psSelectInfo->query_mode == SWQM_DISTINCT_LIST)
706
0
    {
707
0
        if (!PrepareSummary())
708
0
            return 0;
709
710
0
        if (psSelectInfo->column_summary.empty())
711
0
            return 0;
712
713
0
        nRet = psSelectInfo->column_summary[0].count;
714
0
    }
715
0
    else if (psSelectInfo->query_mode != SWQM_RECORDSET)
716
0
        return 1;
717
0
    else if (m_poAttrQuery == nullptr && !MustEvaluateSpatialFilterOnGenSQL())
718
0
    {
719
0
        nRet = m_poSrcLayer->GetFeatureCount(bForce);
720
0
    }
721
0
    else
722
0
    {
723
0
        nRet = OGRLayer::GetFeatureCount(bForce);
724
0
    }
725
0
    if (nRet < 0)
726
0
        return nRet;
727
728
0
    nRet = std::max(static_cast<GIntBig>(0), nRet - psSelectInfo->offset);
729
0
    if (psSelectInfo->limit >= 0)
730
0
        nRet = std::min(nRet, psSelectInfo->limit);
731
0
    return nRet;
732
0
}
733
734
/************************************************************************/
735
/*                           TestCapability()                           */
736
/************************************************************************/
737
738
int OGRGenSQLResultsLayer::TestCapability(const char *pszCap) const
739
740
0
{
741
0
    const swq_select *psSelectInfo = m_pSelectInfo.get();
742
743
0
    if (EQUAL(pszCap, OLCFastSetNextByIndex))
744
0
    {
745
0
        if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD ||
746
0
            psSelectInfo->query_mode == SWQM_DISTINCT_LIST ||
747
0
            !m_anFIDIndex.empty())
748
0
            return TRUE;
749
0
        else
750
0
            return m_poSrcLayer->TestCapability(pszCap);
751
0
    }
752
753
0
    if (psSelectInfo->query_mode == SWQM_RECORDSET &&
754
0
        (EQUAL(pszCap, OLCFastFeatureCount) || EQUAL(pszCap, OLCRandomRead) ||
755
0
         EQUAL(pszCap, OLCFastGetExtent)))
756
0
        return m_poSrcLayer->TestCapability(pszCap);
757
758
0
    else if (psSelectInfo->query_mode != SWQM_RECORDSET)
759
0
    {
760
0
        if (EQUAL(pszCap, OLCFastFeatureCount))
761
0
            return TRUE;
762
0
    }
763
764
0
    if (EQUAL(pszCap, OLCStringsAsUTF8) || EQUAL(pszCap, OLCCurveGeometries) ||
765
0
        EQUAL(pszCap, OLCMeasuredGeometries) || EQUAL(pszCap, OLCZGeometries))
766
0
    {
767
0
        return m_poSrcLayer->TestCapability(pszCap);
768
0
    }
769
770
0
    else if (EQUAL(pszCap, OLCFastGetArrowStream))
771
0
    {
772
        // Make sure the SQL is something as simple as
773
        // "SELECT field1 [AS renamed], ... FROM ... WHERE ....", without
774
        // duplicated fields
775
0
        if (m_bForwardWhereToSourceLayer &&
776
0
            psSelectInfo->query_mode == SWQM_RECORDSET &&
777
0
            psSelectInfo->offset == 0 && psSelectInfo->join_count == 0 &&
778
0
            psSelectInfo->order_specs == 0)
779
0
        {
780
0
            std::set<int> oSetFieldIndex;
781
0
            int nLastIdxRegularField = -1;
782
0
            for (std::size_t iField = 0;
783
0
                 iField < psSelectInfo->column_defs.size(); iField++)
784
0
            {
785
0
                const swq_col_def *psColDef =
786
0
                    &psSelectInfo->column_defs[iField];
787
0
                if (psColDef->bHidden || psColDef->table_index < 0 ||
788
0
                    psColDef->col_func != SWQCF_NONE ||
789
0
                    cpl::contains(oSetFieldIndex, psColDef->field_index))
790
0
                {
791
0
                    return false;
792
0
                }
793
794
0
                oSetFieldIndex.insert(psColDef->field_index);
795
796
0
                const auto poLayerDefn =
797
0
                    m_apoTableLayers[psColDef->table_index]->GetLayerDefn();
798
799
0
                if (psColDef->field_index >= 0 && poLayerDefn != nullptr &&
800
0
                    psColDef->field_index < poLayerDefn->GetFieldCount())
801
0
                {
802
                    // We do not support re-ordered fields
803
0
                    if (psColDef->field_index <= nLastIdxRegularField)
804
0
                        return false;
805
0
                    nLastIdxRegularField = psColDef->field_index;
806
0
                }
807
0
                else if (poLayerDefn != nullptr &&
808
0
                         IS_GEOM_FIELD_INDEX(poLayerDefn,
809
0
                                             psColDef->field_index))
810
0
                {
811
                    // ok
812
0
                }
813
0
                else
814
0
                {
815
0
                    return false;
816
0
                }
817
0
            }
818
0
            return m_poSrcLayer->TestCapability(pszCap);
819
0
        }
820
0
    }
821
822
0
    return FALSE;
823
0
}
824
825
/************************************************************************/
826
/*                      ContainGeomSpecialField()                       */
827
/************************************************************************/
828
829
int OGRGenSQLResultsLayer::ContainGeomSpecialField(
830
    const swq_expr_node *expr) const
831
0
{
832
0
    if (expr->eNodeType == SNT_COLUMN)
833
0
    {
834
0
        if (expr->table_index == 0 && expr->field_index != -1)
835
0
        {
836
0
            OGRLayer *poLayer = m_apoTableLayers[expr->table_index];
837
0
            int nSpecialFieldIdx =
838
0
                expr->field_index - poLayer->GetLayerDefn()->GetFieldCount();
839
0
            if (nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
840
0
                nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
841
0
                nSpecialFieldIdx == SPF_OGR_GEOM_AREA)
842
0
                return TRUE;
843
0
            if (expr->field_index ==
844
0
                GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poLayer->GetLayerDefn(), 0))
845
0
                return TRUE;
846
0
            return FALSE;
847
0
        }
848
0
    }
849
0
    else if (expr->eNodeType == SNT_OPERATION)
850
0
    {
851
0
        for (int i = 0; i < expr->nSubExprCount; i++)
852
0
        {
853
0
            if (ContainGeomSpecialField(expr->papoSubExpr[i]))
854
0
                return TRUE;
855
0
        }
856
0
    }
857
0
    return FALSE;
858
0
}
859
860
/************************************************************************/
861
/*                           PrepareSummary()                           */
862
/************************************************************************/
863
864
bool OGRGenSQLResultsLayer::PrepareSummary() const
865
866
0
{
867
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
868
869
0
    if (m_poSummaryFeature)
870
0
        return true;
871
872
0
    m_poSummaryFeature = std::make_unique<OGRFeature>(m_poDefn);
873
0
    m_poSummaryFeature->SetFID(0);
874
875
    /* -------------------------------------------------------------------- */
876
    /*      Ensure our query parameters are in place on the source          */
877
    /*      layer.  And initialize reading.                                 */
878
    /* -------------------------------------------------------------------- */
879
0
    const_cast<OGRGenSQLResultsLayer *>(this)->ApplyFiltersToSource();
880
881
    /* -------------------------------------------------------------------- */
882
    /*      Ignore geometry reading if no spatial filter in place and that  */
883
    /*      the where clause and no column references OGR_GEOMETRY,         */
884
    /*      OGR_GEOM_WKT or OGR_GEOM_AREA special fields.                   */
885
    /* -------------------------------------------------------------------- */
886
887
0
    struct TempGeomIgnoredSetter
888
0
    {
889
0
        OGRFeatureDefn &m_oDefn;
890
0
        const int m_bSaveIsGeomIgnored;
891
892
0
        explicit TempGeomIgnoredSetter(OGRFeatureDefn *poDefn)
893
0
            : m_oDefn(*poDefn),
894
0
              m_bSaveIsGeomIgnored(poDefn->IsGeometryIgnored())
895
0
        {
896
0
            m_oDefn.SetGeometryIgnored(true);
897
0
        }
898
899
0
        ~TempGeomIgnoredSetter()
900
0
        {
901
0
            m_oDefn.SetGeometryIgnored(m_bSaveIsGeomIgnored);
902
0
        }
903
0
    };
904
905
0
    auto poSrcLayerDefn = m_poSrcLayer->GetLayerDefn();
906
0
    std::unique_ptr<TempGeomIgnoredSetter> oTempGeomIgnoredSetter;
907
908
0
    if (!m_bSpatialFilterSetOnSourceLayer && m_poFilterGeom == nullptr &&
909
0
        (psSelectInfo->where_expr == nullptr ||
910
0
         !ContainGeomSpecialField(psSelectInfo->where_expr)))
911
0
    {
912
0
        bool bFoundGeomExpr = false;
913
0
        for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
914
0
        {
915
0
            const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
916
0
            if (psColDef->table_index == 0 && psColDef->field_index != -1)
917
0
            {
918
0
                OGRLayer *poLayer = m_apoTableLayers[psColDef->table_index];
919
0
                const int nSpecialFieldIdx =
920
0
                    psColDef->field_index -
921
0
                    poLayer->GetLayerDefn()->GetFieldCount();
922
0
                if (nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
923
0
                    nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
924
0
                    nSpecialFieldIdx == SPF_OGR_GEOM_AREA)
925
0
                {
926
0
                    bFoundGeomExpr = true;
927
0
                    break;
928
0
                }
929
0
                if (psColDef->field_index ==
930
0
                    GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poLayer->GetLayerDefn(),
931
0
                                                        0))
932
0
                {
933
0
                    bFoundGeomExpr = true;
934
0
                    break;
935
0
                }
936
0
            }
937
0
            if (psColDef->expr != nullptr &&
938
0
                ContainGeomSpecialField(psColDef->expr))
939
0
            {
940
0
                bFoundGeomExpr = true;
941
0
                break;
942
0
            }
943
0
        }
944
0
        if (!bFoundGeomExpr)
945
0
        {
946
            // cppcheck-suppress unreadVariable
947
0
            oTempGeomIgnoredSetter =
948
0
                std::make_unique<TempGeomIgnoredSetter>(poSrcLayerDefn);
949
0
        }
950
0
    }
951
952
    /* -------------------------------------------------------------------- */
953
    /*      We treat COUNT(*) as a special case, and fill with              */
954
    /*      GetFeatureCount().                                              */
955
    /* -------------------------------------------------------------------- */
956
957
0
    if (psSelectInfo->result_columns() == 1 &&
958
0
        psSelectInfo->column_defs[0].col_func == SWQCF_COUNT &&
959
0
        psSelectInfo->column_defs[0].field_index < 0)
960
0
    {
961
0
        GIntBig nRes = m_poSrcLayer->GetFeatureCount(TRUE);
962
0
        m_poSummaryFeature->SetField(0, nRes);
963
964
0
        if (CPL_INT64_FITS_ON_INT32(nRes))
965
0
        {
966
0
            m_poSummaryFeature.reset();
967
0
            m_poDefn->GetFieldDefn(0)->SetType(OFTInteger);
968
0
            m_poSummaryFeature = std::make_unique<OGRFeature>(m_poDefn);
969
0
            m_poSummaryFeature->SetFID(0);
970
0
            m_poSummaryFeature->SetField(0, static_cast<int>(nRes));
971
0
        }
972
973
0
        return TRUE;
974
0
    }
975
976
    /* -------------------------------------------------------------------- */
977
    /*      Otherwise, process all source feature through the summary       */
978
    /*      building facilities of SWQ.                                     */
979
    /* -------------------------------------------------------------------- */
980
981
0
    for (auto &&poSrcFeature : *m_poSrcLayer)
982
0
    {
983
0
        for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
984
0
        {
985
0
            const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
986
0
            const char *pszError = nullptr;
987
988
0
            if (psColDef->col_func == SWQCF_COUNT)
989
0
            {
990
                /* psColDef->field_index can be -1 in the case of a COUNT(*) */
991
0
                if (psColDef->field_index < 0)
992
0
                    pszError =
993
0
                        swq_select_summarize(psSelectInfo, iField, "", nullptr);
994
0
                else if (IS_GEOM_FIELD_INDEX(poSrcLayerDefn,
995
0
                                             psColDef->field_index))
996
0
                {
997
0
                    const int iSrcGeomField =
998
0
                        ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
999
0
                            poSrcLayerDefn, psColDef->field_index);
1000
0
                    const OGRGeometry *poGeom =
1001
0
                        poSrcFeature->GetGeomFieldRef(iSrcGeomField);
1002
0
                    if (poGeom != nullptr)
1003
0
                        pszError = swq_select_summarize(psSelectInfo, iField,
1004
0
                                                        "", nullptr);
1005
0
                }
1006
0
                else if (poSrcFeature->IsFieldSetAndNotNull(
1007
0
                             psColDef->field_index))
1008
0
                {
1009
0
                    if (!psColDef->distinct_flag)
1010
0
                    {
1011
0
                        pszError = swq_select_summarize(psSelectInfo, iField,
1012
0
                                                        "", nullptr);
1013
0
                    }
1014
0
                    else
1015
0
                    {
1016
0
                        const char *pszVal = poSrcFeature->GetFieldAsString(
1017
0
                            psColDef->field_index);
1018
0
                        pszError = swq_select_summarize(psSelectInfo, iField,
1019
0
                                                        pszVal, nullptr);
1020
0
                    }
1021
0
                }
1022
0
            }
1023
0
            else
1024
0
            {
1025
0
                if (poSrcFeature->IsFieldSetAndNotNull(psColDef->field_index))
1026
0
                {
1027
0
                    if (!psColDef->distinct_flag &&
1028
0
                        (psColDef->field_type == SWQ_BOOLEAN ||
1029
0
                         psColDef->field_type == SWQ_INTEGER ||
1030
0
                         psColDef->field_type == SWQ_INTEGER64 ||
1031
0
                         psColDef->field_type == SWQ_FLOAT))
1032
0
                    {
1033
0
                        const double dfValue = poSrcFeature->GetFieldAsDouble(
1034
0
                            psColDef->field_index);
1035
0
                        pszError = swq_select_summarize(psSelectInfo, iField,
1036
0
                                                        nullptr, &dfValue);
1037
0
                    }
1038
0
                    else
1039
0
                    {
1040
0
                        const char *pszVal = poSrcFeature->GetFieldAsString(
1041
0
                            psColDef->field_index);
1042
0
                        pszError = swq_select_summarize(psSelectInfo, iField,
1043
0
                                                        pszVal, nullptr);
1044
0
                    }
1045
0
                }
1046
0
                else
1047
0
                {
1048
0
                    pszError = swq_select_summarize(psSelectInfo, iField,
1049
0
                                                    nullptr, nullptr);
1050
0
                }
1051
0
            }
1052
1053
0
            if (pszError)
1054
0
            {
1055
0
                m_poSummaryFeature.reset();
1056
1057
0
                CPLError(CE_Failure, CPLE_AppDefined, "%s", pszError);
1058
0
                return false;
1059
0
            }
1060
0
        }
1061
0
    }
1062
1063
    /* -------------------------------------------------------------------- */
1064
    /*      Clear away the filters we have installed till a next run through*/
1065
    /*      the features.                                                   */
1066
    /* -------------------------------------------------------------------- */
1067
0
    const_cast<OGRGenSQLResultsLayer *>(this)->ClearFilters();
1068
1069
    /* -------------------------------------------------------------------- */
1070
    /*      Now apply the values to the summary feature.  If we are in      */
1071
    /*      DISTINCT_LIST mode we don't do this step.                       */
1072
    /* -------------------------------------------------------------------- */
1073
0
    if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD)
1074
0
    {
1075
0
        for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1076
0
        {
1077
0
            const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1078
0
            if (!psSelectInfo->column_summary.empty())
1079
0
            {
1080
0
                const swq_summary &oSummary =
1081
0
                    psSelectInfo->column_summary[iField];
1082
0
                if (psColDef->col_func == SWQCF_COUNT)
1083
0
                {
1084
0
                    if (CPL_INT64_FITS_ON_INT32(oSummary.count))
1085
0
                    {
1086
0
                        m_poSummaryFeature.reset();
1087
0
                        m_poDefn->GetFieldDefn(iField)->SetType(OFTInteger);
1088
0
                    }
1089
0
                }
1090
0
            }
1091
0
        }
1092
1093
0
        if (!m_poSummaryFeature)
1094
0
        {
1095
0
            m_poSummaryFeature = std::make_unique<OGRFeature>(m_poDefn);
1096
0
            m_poSummaryFeature->SetFID(0);
1097
0
        }
1098
1099
0
        for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1100
0
        {
1101
0
            const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1102
0
            if (!psSelectInfo->column_summary.empty())
1103
0
            {
1104
0
                const swq_summary &oSummary =
1105
0
                    psSelectInfo->column_summary[iField];
1106
1107
0
                switch (psColDef->col_func)
1108
0
                {
1109
0
                    case SWQCF_NONE:
1110
0
                    case SWQCF_CUSTOM:
1111
0
                        break;
1112
1113
0
                    case SWQCF_AVG:
1114
0
                    {
1115
0
                        if (oSummary.count > 0)
1116
0
                        {
1117
0
                            const double dfAvg =
1118
0
                                oSummary.sum() / oSummary.count;
1119
0
                            if (psColDef->field_type == SWQ_DATE ||
1120
0
                                psColDef->field_type == SWQ_TIME ||
1121
0
                                psColDef->field_type == SWQ_TIMESTAMP)
1122
0
                            {
1123
0
                                struct tm brokendowntime;
1124
0
                                CPLUnixTimeToYMDHMS(static_cast<GIntBig>(dfAvg),
1125
0
                                                    &brokendowntime);
1126
0
                                m_poSummaryFeature->SetField(
1127
0
                                    iField, brokendowntime.tm_year + 1900,
1128
0
                                    brokendowntime.tm_mon + 1,
1129
0
                                    brokendowntime.tm_mday,
1130
0
                                    brokendowntime.tm_hour,
1131
0
                                    brokendowntime.tm_min,
1132
0
                                    static_cast<float>(brokendowntime.tm_sec +
1133
0
                                                       fmod(dfAvg, 1)),
1134
0
                                    0);
1135
0
                            }
1136
0
                            else
1137
0
                            {
1138
0
                                m_poSummaryFeature->SetField(iField, dfAvg);
1139
0
                            }
1140
0
                        }
1141
0
                        break;
1142
0
                    }
1143
1144
0
                    case SWQCF_MIN:
1145
0
                    {
1146
0
                        if (oSummary.count > 0)
1147
0
                        {
1148
0
                            if (psColDef->field_type == SWQ_DATE ||
1149
0
                                psColDef->field_type == SWQ_TIME ||
1150
0
                                psColDef->field_type == SWQ_TIMESTAMP ||
1151
0
                                psColDef->field_type == SWQ_STRING)
1152
0
                                m_poSummaryFeature->SetField(
1153
0
                                    iField, oSummary.osMin.c_str());
1154
0
                            else
1155
0
                                m_poSummaryFeature->SetField(iField,
1156
0
                                                             oSummary.min);
1157
0
                        }
1158
0
                        break;
1159
0
                    }
1160
1161
0
                    case SWQCF_MAX:
1162
0
                    {
1163
0
                        if (oSummary.count > 0)
1164
0
                        {
1165
0
                            if (psColDef->field_type == SWQ_DATE ||
1166
0
                                psColDef->field_type == SWQ_TIME ||
1167
0
                                psColDef->field_type == SWQ_TIMESTAMP ||
1168
0
                                psColDef->field_type == SWQ_STRING)
1169
0
                                m_poSummaryFeature->SetField(
1170
0
                                    iField, oSummary.osMax.c_str());
1171
0
                            else
1172
0
                                m_poSummaryFeature->SetField(iField,
1173
0
                                                             oSummary.max);
1174
0
                        }
1175
0
                        break;
1176
0
                    }
1177
1178
0
                    case SWQCF_COUNT:
1179
0
                    {
1180
0
                        m_poSummaryFeature->SetField(iField, oSummary.count);
1181
0
                        break;
1182
0
                    }
1183
1184
0
                    case SWQCF_SUM:
1185
0
                    {
1186
0
                        if (oSummary.count > 0)
1187
0
                            m_poSummaryFeature->SetField(iField,
1188
0
                                                         oSummary.sum());
1189
0
                        break;
1190
0
                    }
1191
1192
0
                    case SWQCF_STDDEV_POP:
1193
0
                    {
1194
0
                        if (oSummary.count > 0)
1195
0
                        {
1196
0
                            const double dfVariance =
1197
0
                                oSummary.sq_dist_from_mean_acc / oSummary.count;
1198
0
                            m_poSummaryFeature->SetField(iField,
1199
0
                                                         sqrt(dfVariance));
1200
0
                        }
1201
0
                        break;
1202
0
                    }
1203
1204
0
                    case SWQCF_STDDEV_SAMP:
1205
0
                    {
1206
0
                        if (oSummary.count > 1)
1207
0
                        {
1208
0
                            const double dfSampleVariance =
1209
0
                                oSummary.sq_dist_from_mean_acc /
1210
0
                                (oSummary.count - 1);
1211
0
                            m_poSummaryFeature->SetField(
1212
0
                                iField, sqrt(dfSampleVariance));
1213
0
                        }
1214
0
                        break;
1215
0
                    }
1216
0
                }
1217
0
            }
1218
0
            else if (psColDef->col_func == SWQCF_COUNT)
1219
0
                m_poSummaryFeature->SetField(iField, 0);
1220
0
        }
1221
0
    }
1222
1223
0
    return TRUE;
1224
0
}
1225
1226
/************************************************************************/
1227
/*                       OGRMultiFeatureFetcher()                       */
1228
/************************************************************************/
1229
1230
typedef std::vector<std::unique_ptr<OGRFeature>> VectorOfUniquePtrFeature;
1231
1232
static swq_expr_node *OGRMultiFeatureFetcher(swq_expr_node *op,
1233
                                             void *pFeatureList)
1234
1235
0
{
1236
0
    auto &apoFeatures =
1237
0
        *(static_cast<VectorOfUniquePtrFeature *>(pFeatureList));
1238
0
    swq_expr_node *poRetNode = nullptr;
1239
1240
0
    CPLAssert(op->eNodeType == SNT_COLUMN);
1241
1242
    /* -------------------------------------------------------------------- */
1243
    /*      What feature are we using?  The primary or one of the joined ones?*/
1244
    /* -------------------------------------------------------------------- */
1245
0
    if (op->table_index < 0 ||
1246
0
        op->table_index >= static_cast<int>(apoFeatures.size()))
1247
0
    {
1248
0
        CPLError(CE_Failure, CPLE_AppDefined,
1249
0
                 "Request for unexpected table_index (%d) in field fetcher.",
1250
0
                 op->table_index);
1251
0
        return nullptr;
1252
0
    }
1253
1254
0
    OGRFeature *poFeature = apoFeatures[op->table_index].get();
1255
1256
    /* -------------------------------------------------------------------- */
1257
    /*      Fetch the value.                                                */
1258
    /* -------------------------------------------------------------------- */
1259
0
    switch (op->field_type)
1260
0
    {
1261
0
        case SWQ_INTEGER:
1262
0
        case SWQ_BOOLEAN:
1263
0
            if (poFeature == nullptr ||
1264
0
                !poFeature->IsFieldSetAndNotNull(op->field_index))
1265
0
            {
1266
0
                poRetNode = new swq_expr_node(0);
1267
0
                poRetNode->is_null = TRUE;
1268
0
            }
1269
0
            else
1270
0
                poRetNode = new swq_expr_node(
1271
0
                    poFeature->GetFieldAsInteger(op->field_index));
1272
0
            break;
1273
1274
0
        case SWQ_INTEGER64:
1275
0
            if (poFeature == nullptr ||
1276
0
                !poFeature->IsFieldSetAndNotNull(op->field_index))
1277
0
            {
1278
0
                poRetNode = new swq_expr_node(static_cast<GIntBig>(0));
1279
0
                poRetNode->is_null = TRUE;
1280
0
            }
1281
0
            else
1282
0
                poRetNode = new swq_expr_node(
1283
0
                    poFeature->GetFieldAsInteger64(op->field_index));
1284
0
            break;
1285
1286
0
        case SWQ_FLOAT:
1287
0
            if (poFeature == nullptr ||
1288
0
                !poFeature->IsFieldSetAndNotNull(op->field_index))
1289
0
            {
1290
0
                poRetNode = new swq_expr_node(0.0);
1291
0
                poRetNode->is_null = TRUE;
1292
0
            }
1293
0
            else
1294
0
                poRetNode = new swq_expr_node(
1295
0
                    poFeature->GetFieldAsDouble(op->field_index));
1296
0
            break;
1297
1298
0
        case SWQ_GEOMETRY:
1299
0
            if (poFeature == nullptr)
1300
0
            {
1301
0
                poRetNode =
1302
0
                    new swq_expr_node(static_cast<OGRGeometry *>(nullptr));
1303
0
            }
1304
0
            else
1305
0
            {
1306
0
                int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
1307
0
                    poFeature->GetDefnRef(), op->field_index);
1308
0
                poRetNode = new swq_expr_node(
1309
0
                    poFeature->GetGeomFieldRef(iSrcGeomField));
1310
0
            }
1311
0
            break;
1312
1313
0
        default:
1314
0
            if (poFeature == nullptr ||
1315
0
                !poFeature->IsFieldSetAndNotNull(op->field_index))
1316
0
            {
1317
0
                poRetNode = new swq_expr_node("");
1318
0
                poRetNode->is_null = TRUE;
1319
0
            }
1320
0
            else
1321
0
                poRetNode = new swq_expr_node(
1322
0
                    poFeature->GetFieldAsString(op->field_index));
1323
0
            break;
1324
0
    }
1325
1326
0
    return poRetNode;
1327
0
}
1328
1329
/************************************************************************/
1330
/*                          GetFilterForJoin()                          */
1331
/************************************************************************/
1332
1333
static CPLString GetFilterForJoin(swq_expr_node *poExpr, OGRFeature *poSrcFeat,
1334
                                  OGRLayer *poJoinLayer, int secondary_table)
1335
0
{
1336
0
    if (poExpr->eNodeType == SNT_CONSTANT)
1337
0
    {
1338
0
        char *pszRes = poExpr->Unparse(nullptr, '"');
1339
0
        CPLString osRes(pszRes);
1340
0
        CPLFree(pszRes);
1341
0
        return osRes;
1342
0
    }
1343
1344
0
    if (poExpr->eNodeType == SNT_COLUMN)
1345
0
    {
1346
0
        CPLAssert(poExpr->field_index != -1);
1347
0
        CPLAssert(poExpr->table_index == 0 ||
1348
0
                  poExpr->table_index == secondary_table);
1349
1350
0
        if (poExpr->table_index == 0)
1351
0
        {
1352
            // if source key is null, we can't do join.
1353
0
            if (!poSrcFeat->IsFieldSetAndNotNull(poExpr->field_index))
1354
0
            {
1355
0
                return "";
1356
0
            }
1357
0
            const auto poSrcFDefn = poSrcFeat->GetDefnRef();
1358
0
            if (poExpr->field_index >= poSrcFDefn->GetFieldCount())
1359
0
            {
1360
0
                CPLAssert(poExpr->field_index <
1361
0
                          poSrcFDefn->GetFieldCount() + SPECIAL_FIELD_COUNT);
1362
0
                CPLString osRes;
1363
0
                switch (SpecialFieldTypes[poExpr->field_index -
1364
0
                                          poSrcFDefn->GetFieldCount()])
1365
0
                {
1366
0
                    case SWQ_INTEGER:
1367
0
                    case SWQ_INTEGER64:
1368
0
                        osRes = CPLString().Printf(
1369
0
                            CPL_FRMT_GIB, poSrcFeat->GetFieldAsInteger64(
1370
0
                                              poExpr->field_index));
1371
0
                        break;
1372
1373
0
                    case SWQ_FLOAT:
1374
0
                        osRes = CPLString().Printf(
1375
0
                            "%.17g",
1376
0
                            poSrcFeat->GetFieldAsDouble(poExpr->field_index));
1377
0
                        break;
1378
1379
0
                    default:
1380
0
                    {
1381
0
                        char *pszEscaped = CPLEscapeString(
1382
0
                            poSrcFeat->GetFieldAsString(poExpr->field_index),
1383
0
                            -1, CPLES_SQL);
1384
0
                        osRes = "'";
1385
0
                        osRes += pszEscaped;
1386
0
                        osRes += "'";
1387
0
                        CPLFree(pszEscaped);
1388
0
                        break;
1389
0
                    }
1390
0
                }
1391
0
                return osRes;
1392
0
            }
1393
0
            else
1394
0
            {
1395
0
                const OGRFieldType ePrimaryFieldType =
1396
0
                    poSrcFeat->GetFieldDefnRef(poExpr->field_index)->GetType();
1397
0
                const OGRField *psSrcField =
1398
0
                    poSrcFeat->GetRawFieldRef(poExpr->field_index);
1399
1400
0
                CPLString osRet;
1401
0
                switch (ePrimaryFieldType)
1402
0
                {
1403
0
                    case OFTInteger:
1404
0
                        osRet.Printf("%d", psSrcField->Integer);
1405
0
                        break;
1406
1407
0
                    case OFTInteger64:
1408
0
                        osRet.Printf(CPL_FRMT_GIB, psSrcField->Integer64);
1409
0
                        break;
1410
1411
0
                    case OFTReal:
1412
0
                        osRet.Printf("%.17g", psSrcField->Real);
1413
0
                        break;
1414
1415
0
                    case OFTString:
1416
0
                    {
1417
0
                        char *pszEscaped = CPLEscapeString(
1418
0
                            psSrcField->String,
1419
0
                            static_cast<int>(strlen(psSrcField->String)),
1420
0
                            CPLES_SQL);
1421
0
                        osRet = "'";
1422
0
                        osRet += pszEscaped;
1423
0
                        osRet += "'";
1424
0
                        CPLFree(pszEscaped);
1425
0
                        break;
1426
0
                    }
1427
1428
0
                    default:
1429
0
                        CPLAssert(false);
1430
0
                        break;
1431
0
                }
1432
1433
0
                return osRet;
1434
0
            }
1435
0
        }
1436
1437
0
        if (poExpr->table_index == secondary_table)
1438
0
        {
1439
0
            const auto poJoinFDefn = poJoinLayer->GetLayerDefn();
1440
0
            if (poExpr->field_index >= poJoinFDefn->GetFieldCount())
1441
0
            {
1442
0
                CPLAssert(poExpr->field_index <
1443
0
                          poJoinFDefn->GetFieldCount() + SPECIAL_FIELD_COUNT);
1444
0
                return SpecialFieldNames[poExpr->field_index -
1445
0
                                         poJoinFDefn->GetFieldCount()];
1446
0
            }
1447
0
            else
1448
0
            {
1449
0
                const OGRFieldDefn *poSecondaryFieldDefn =
1450
0
                    poJoinFDefn->GetFieldDefn(poExpr->field_index);
1451
0
                return CPLSPrintf("\"%s\"", poSecondaryFieldDefn->GetNameRef());
1452
0
            }
1453
0
        }
1454
1455
0
        CPLAssert(false);
1456
0
        return "";
1457
0
    }
1458
1459
0
    if (poExpr->eNodeType == SNT_OPERATION)
1460
0
    {
1461
        /* ----------------------------------------------------------------- */
1462
        /*      Operation - start by unparsing all the subexpressions.       */
1463
        /* ----------------------------------------------------------------- */
1464
0
        std::vector<char *> apszSubExpr;
1465
0
        for (int i = 0; i < poExpr->nSubExprCount; i++)
1466
0
        {
1467
0
            CPLString osSubExpr =
1468
0
                GetFilterForJoin(poExpr->papoSubExpr[i], poSrcFeat, poJoinLayer,
1469
0
                                 secondary_table);
1470
0
            if (osSubExpr.empty())
1471
0
            {
1472
0
                for (--i; i >= 0; i--)
1473
0
                    CPLFree(apszSubExpr[i]);
1474
0
                return "";
1475
0
            }
1476
0
            apszSubExpr.push_back(CPLStrdup(osSubExpr));
1477
0
        }
1478
1479
0
        CPLString osExpr =
1480
0
            poExpr->UnparseOperationFromUnparsedSubExpr(&apszSubExpr[0]);
1481
1482
        /* ----------------------------------------------------------------- */
1483
        /*      cleanup subexpressions.                                      */
1484
        /* ----------------------------------------------------------------- */
1485
0
        for (int i = 0; i < poExpr->nSubExprCount; i++)
1486
0
            CPLFree(apszSubExpr[i]);
1487
1488
0
        return osExpr;
1489
0
    }
1490
1491
0
    return "";
1492
0
}
1493
1494
/************************************************************************/
1495
/*                          TranslateFeature()                          */
1496
/************************************************************************/
1497
1498
std::unique_ptr<OGRFeature> OGRGenSQLResultsLayer::TranslateFeature(
1499
    std::unique_ptr<OGRFeature> poSrcFeatUniquePtr)
1500
1501
0
{
1502
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
1503
0
    VectorOfUniquePtrFeature apoFeatures;
1504
1505
0
    if (poSrcFeatUniquePtr == nullptr)
1506
0
        return nullptr;
1507
1508
0
    m_nFeaturesRead++;
1509
1510
0
    apoFeatures.push_back(std::move(poSrcFeatUniquePtr));
1511
0
    auto poSrcFeat = apoFeatures.front().get();
1512
1513
    /* -------------------------------------------------------------------- */
1514
    /*      Fetch the corresponding features from any jointed tables.       */
1515
    /* -------------------------------------------------------------------- */
1516
0
    for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
1517
0
    {
1518
0
        const swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
1519
1520
        /* OGRMultiFeatureFetcher assumes that the features are pushed in */
1521
        /* apoFeatures with increasing secondary_table, so make sure */
1522
        /* we have taken care of this */
1523
0
        CPLAssert(psJoinInfo->secondary_table == iJoin + 1);
1524
1525
0
        OGRLayer *poJoinLayer = m_apoTableLayers[psJoinInfo->secondary_table];
1526
1527
0
        const std::string osFilter =
1528
0
            GetFilterForJoin(psJoinInfo->poExpr, poSrcFeat, poJoinLayer,
1529
0
                             psJoinInfo->secondary_table);
1530
        // CPLDebug("OGR", "Filter = %s\n", osFilter.c_str());
1531
1532
        // if source key is null, we can't do join.
1533
0
        if (osFilter.empty())
1534
0
        {
1535
0
            apoFeatures.push_back(nullptr);
1536
0
            continue;
1537
0
        }
1538
1539
0
        std::unique_ptr<OGRFeature> poJoinFeature;
1540
1541
0
        poJoinLayer->ResetReading();
1542
0
        if (poJoinLayer->SetAttributeFilter(osFilter.c_str()) == OGRERR_NONE)
1543
0
            poJoinFeature.reset(poJoinLayer->GetNextFeature());
1544
1545
0
        apoFeatures.push_back(std::move(poJoinFeature));
1546
0
    }
1547
1548
    /* -------------------------------------------------------------------- */
1549
    /*      Create destination feature.                                     */
1550
    /* -------------------------------------------------------------------- */
1551
0
    auto poDstFeat = std::make_unique<OGRFeature>(m_poDefn);
1552
1553
0
    poDstFeat->SetFID(poSrcFeat->GetFID());
1554
1555
0
    poDstFeat->SetStyleString(poSrcFeat->GetStyleString());
1556
0
    poDstFeat->SetNativeData(poSrcFeat->GetNativeData());
1557
0
    poDstFeat->SetNativeMediaType(poSrcFeat->GetNativeMediaType());
1558
1559
    /* -------------------------------------------------------------------- */
1560
    /*      Evaluate fields that are complex expressions.                   */
1561
    /* -------------------------------------------------------------------- */
1562
0
    int iRegularField = 0;
1563
0
    int iGeomField = 0;
1564
0
    swq_evaluation_context sContext;
1565
0
    for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1566
0
    {
1567
0
        const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1568
1569
0
        if (psColDef->bHidden)
1570
0
        {
1571
0
            const char *pszDstFieldName = psColDef->field_alias
1572
0
                                              ? psColDef->field_alias
1573
0
                                              : psColDef->field_name;
1574
0
            if (EQUAL(pszDstFieldName, "OGR_STYLE"))
1575
0
            {
1576
0
                if (psColDef->field_type == SWQ_STRING)
1577
0
                {
1578
                    // Does this column definition directly references a
1579
                    // source field ?
1580
0
                    if (psColDef->field_index >= 0)
1581
0
                    {
1582
0
                        if (!IS_GEOM_FIELD_INDEX(poSrcFeat->GetDefnRef(),
1583
0
                                                 psColDef->field_index))
1584
0
                        {
1585
0
                            if (poSrcFeat->IsFieldSetAndNotNull(
1586
0
                                    psColDef->field_index))
1587
0
                            {
1588
0
                                const char *pszVal =
1589
0
                                    poSrcFeat->GetFieldAsString(
1590
0
                                        psColDef->field_index);
1591
0
                                poDstFeat->SetStyleString(pszVal);
1592
0
                            }
1593
0
                            else
1594
0
                            {
1595
0
                                poDstFeat->SetStyleString(nullptr);
1596
0
                            }
1597
0
                        }
1598
0
                        else
1599
0
                        {
1600
0
                            CPLError(CE_Warning, CPLE_AppDefined,
1601
0
                                     "OGR_STYLE HIDDEN field should reference "
1602
0
                                     "a column of type String");
1603
0
                        }
1604
0
                    }
1605
0
                    else
1606
0
                    {
1607
0
                        auto poResult = std::unique_ptr<swq_expr_node>(
1608
0
                            psColDef->expr->Evaluate(OGRMultiFeatureFetcher,
1609
0
                                                     &apoFeatures, sContext));
1610
1611
0
                        if (!poResult)
1612
0
                        {
1613
0
                            return nullptr;
1614
0
                        }
1615
1616
0
                        poDstFeat->SetStyleString(poResult->is_null
1617
0
                                                      ? nullptr
1618
0
                                                      : poResult->string_value);
1619
0
                    }
1620
0
                }
1621
0
                else
1622
0
                {
1623
0
                    CPLError(CE_Warning, CPLE_AppDefined,
1624
0
                             "OGR_STYLE HIDDEN field should be of type String");
1625
0
                }
1626
0
            }
1627
0
            continue;
1628
0
        }
1629
1630
        // Does this column definition directly references a
1631
        // source field ?
1632
        // If so, skip it for now, as it will be taken into account in the
1633
        // next loop.
1634
0
        if (psColDef->field_index >= 0)
1635
0
        {
1636
0
            if (psColDef->field_type == SWQ_GEOMETRY ||
1637
0
                psColDef->target_type == SWQ_GEOMETRY)
1638
0
                iGeomField++;
1639
0
            else
1640
0
                iRegularField++;
1641
0
            continue;
1642
0
        }
1643
1644
0
        auto poResult = std::unique_ptr<swq_expr_node>(psColDef->expr->Evaluate(
1645
0
            OGRMultiFeatureFetcher, &apoFeatures, sContext));
1646
1647
0
        if (!poResult)
1648
0
        {
1649
0
            return nullptr;
1650
0
        }
1651
1652
0
        if (poResult->is_null)
1653
0
        {
1654
0
            if (poResult->field_type == SWQ_GEOMETRY)
1655
0
                iGeomField++;
1656
0
            else
1657
0
                iRegularField++;
1658
0
            continue;
1659
0
        }
1660
1661
0
        switch (poResult->field_type)
1662
0
        {
1663
0
            case SWQ_BOOLEAN:
1664
0
            case SWQ_INTEGER:
1665
0
            case SWQ_INTEGER64:
1666
0
                poDstFeat->SetField(iRegularField++,
1667
0
                                    static_cast<GIntBig>(poResult->int_value));
1668
0
                break;
1669
1670
0
            case SWQ_FLOAT:
1671
0
                poDstFeat->SetField(iRegularField++, poResult->float_value);
1672
0
                break;
1673
1674
0
            case SWQ_GEOMETRY:
1675
0
            {
1676
0
                const OGRGenSQLGeomFieldDefn *poGeomFieldDefn =
1677
0
                    cpl::down_cast<const OGRGenSQLGeomFieldDefn *>(
1678
0
                        poDstFeat->GetGeomFieldDefnRef(iGeomField));
1679
0
                if (poGeomFieldDefn->bForceGeomType &&
1680
0
                    poResult->geometry_value != nullptr)
1681
0
                {
1682
0
                    OGRwkbGeometryType eCurType =
1683
0
                        wkbFlatten(poResult->geometry_value->getGeometryType());
1684
0
                    OGRwkbGeometryType eReqType =
1685
0
                        wkbFlatten(poGeomFieldDefn->GetType());
1686
0
                    if (eCurType == wkbPolygon && eReqType == wkbMultiPolygon)
1687
0
                    {
1688
0
                        poResult->geometry_value = OGRGeometry::FromHandle(
1689
0
                            OGR_G_ForceToMultiPolygon(OGRGeometry::ToHandle(
1690
0
                                poResult->geometry_value)));
1691
0
                    }
1692
0
                    else if ((eCurType == wkbMultiPolygon ||
1693
0
                              eCurType == wkbGeometryCollection) &&
1694
0
                             eReqType == wkbPolygon)
1695
0
                    {
1696
0
                        poResult->geometry_value = OGRGeometry::FromHandle(
1697
0
                            OGR_G_ForceToPolygon(OGRGeometry::ToHandle(
1698
0
                                poResult->geometry_value)));
1699
0
                    }
1700
0
                    else if (eCurType == wkbLineString &&
1701
0
                             eReqType == wkbMultiLineString)
1702
0
                    {
1703
0
                        poResult->geometry_value = OGRGeometry::FromHandle(
1704
0
                            OGR_G_ForceToMultiLineString(OGRGeometry::ToHandle(
1705
0
                                poResult->geometry_value)));
1706
0
                    }
1707
0
                    else if ((eCurType == wkbMultiLineString ||
1708
0
                              eCurType == wkbGeometryCollection) &&
1709
0
                             eReqType == wkbLineString)
1710
0
                    {
1711
0
                        poResult->geometry_value = OGRGeometry::FromHandle(
1712
0
                            OGR_G_ForceToLineString(OGRGeometry::ToHandle(
1713
0
                                poResult->geometry_value)));
1714
0
                    }
1715
0
                }
1716
0
                poDstFeat->SetGeomField(iGeomField++, poResult->geometry_value);
1717
0
                break;
1718
0
            }
1719
1720
0
            default:
1721
0
                poDstFeat->SetField(iRegularField++, poResult->string_value);
1722
0
                break;
1723
0
        }
1724
0
    }
1725
1726
    /* -------------------------------------------------------------------- */
1727
    /*      Copy fields from primary record to the destination feature.     */
1728
    /* -------------------------------------------------------------------- */
1729
0
    iRegularField = 0;
1730
0
    iGeomField = 0;
1731
0
    for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1732
0
    {
1733
0
        const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1734
1735
0
        if (psColDef->bHidden)
1736
0
        {
1737
0
            continue;
1738
0
        }
1739
1740
        // Skip this column definition if it doesn't reference a field from
1741
        // the main feature
1742
0
        if (psColDef->table_index != 0)
1743
0
        {
1744
0
            if (psColDef->field_type == SWQ_GEOMETRY ||
1745
0
                psColDef->target_type == SWQ_GEOMETRY)
1746
0
                iGeomField++;
1747
0
            else
1748
0
                iRegularField++;
1749
0
            continue;
1750
0
        }
1751
1752
0
        if (IS_GEOM_FIELD_INDEX(poSrcFeat->GetDefnRef(), psColDef->field_index))
1753
0
        {
1754
0
            int iSrcGeomField = ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
1755
0
                poSrcFeat->GetDefnRef(), psColDef->field_index);
1756
0
            poDstFeat->SetGeomField(iGeomField++,
1757
0
                                    poSrcFeat->GetGeomFieldRef(iSrcGeomField));
1758
0
        }
1759
0
        else if (psColDef->field_index >= m_iFIDFieldIndex)
1760
0
        {
1761
0
            CPLAssert(psColDef->field_index <
1762
0
                      m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
1763
0
            switch (SpecialFieldTypes[psColDef->field_index - m_iFIDFieldIndex])
1764
0
            {
1765
0
                case SWQ_INTEGER:
1766
0
                case SWQ_INTEGER64:
1767
0
                    poDstFeat->SetField(
1768
0
                        iRegularField,
1769
0
                        poSrcFeat->GetFieldAsInteger64(psColDef->field_index));
1770
0
                    break;
1771
0
                case SWQ_FLOAT:
1772
0
                    poDstFeat->SetField(
1773
0
                        iRegularField,
1774
0
                        poSrcFeat->GetFieldAsDouble(psColDef->field_index));
1775
0
                    break;
1776
0
                default:
1777
0
                    poDstFeat->SetField(
1778
0
                        iRegularField,
1779
0
                        poSrcFeat->GetFieldAsString(psColDef->field_index));
1780
0
            }
1781
0
            iRegularField++;
1782
0
        }
1783
0
        else
1784
0
        {
1785
0
            switch (psColDef->target_type)
1786
0
            {
1787
0
                case SWQ_INTEGER:
1788
0
                    poDstFeat->SetField(
1789
0
                        iRegularField,
1790
0
                        poSrcFeat->GetFieldAsInteger(psColDef->field_index));
1791
0
                    break;
1792
1793
0
                case SWQ_INTEGER64:
1794
0
                    poDstFeat->SetField(
1795
0
                        iRegularField,
1796
0
                        poSrcFeat->GetFieldAsInteger64(psColDef->field_index));
1797
0
                    break;
1798
1799
0
                case SWQ_FLOAT:
1800
0
                    poDstFeat->SetField(
1801
0
                        iRegularField,
1802
0
                        poSrcFeat->GetFieldAsDouble(psColDef->field_index));
1803
0
                    break;
1804
1805
0
                case SWQ_STRING:
1806
0
                case SWQ_TIMESTAMP:
1807
0
                case SWQ_DATE:
1808
0
                case SWQ_TIME:
1809
0
                    poDstFeat->SetField(
1810
0
                        iRegularField,
1811
0
                        poSrcFeat->GetFieldAsString(psColDef->field_index));
1812
0
                    break;
1813
1814
0
                case SWQ_GEOMETRY:
1815
0
                    CPLAssert(false);
1816
0
                    break;
1817
1818
0
                default:
1819
0
                    poDstFeat->SetField(
1820
0
                        iRegularField,
1821
0
                        poSrcFeat->GetRawFieldRef(psColDef->field_index));
1822
0
            }
1823
0
            iRegularField++;
1824
0
        }
1825
0
    }
1826
1827
    /* -------------------------------------------------------------------- */
1828
    /*      Copy values from any joined tables.                             */
1829
    /* -------------------------------------------------------------------- */
1830
0
    for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
1831
0
    {
1832
0
        const swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
1833
0
        const OGRFeature *poJoinFeature = apoFeatures[iJoin + 1].get();
1834
1835
0
        if (poJoinFeature == nullptr)
1836
0
            continue;
1837
1838
        // Copy over selected field values.
1839
0
        iRegularField = 0;
1840
0
        for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
1841
0
        {
1842
0
            const swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
1843
1844
0
            if (psColDef->field_type == SWQ_GEOMETRY ||
1845
0
                psColDef->target_type == SWQ_GEOMETRY)
1846
0
                continue;
1847
1848
0
            if (psColDef->bHidden)
1849
0
            {
1850
0
                continue;
1851
0
            }
1852
1853
0
            if (psColDef->table_index == psJoinInfo->secondary_table)
1854
0
                poDstFeat->SetField(
1855
0
                    iRegularField,
1856
0
                    poJoinFeature->GetRawFieldRef(psColDef->field_index));
1857
1858
0
            iRegularField++;
1859
0
        }
1860
0
    }
1861
1862
0
    return poDstFeat;
1863
0
}
1864
1865
/************************************************************************/
1866
/*                           GetNextFeature()                           */
1867
/************************************************************************/
1868
1869
OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
1870
1871
0
{
1872
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
1873
1874
0
    if (m_bEOF)
1875
0
        return nullptr;
1876
0
    if (psSelectInfo->limit >= 0 &&
1877
0
        (m_nIteratedFeatures < 0 ? 0 : m_nIteratedFeatures) >=
1878
0
            psSelectInfo->limit)
1879
0
        return nullptr;
1880
1881
0
    CreateOrderByIndex();
1882
0
    if (m_anFIDIndex.empty() && m_nIteratedFeatures < 0 &&
1883
0
        psSelectInfo->offset > 0 && psSelectInfo->query_mode == SWQM_RECORDSET)
1884
0
    {
1885
0
        m_poSrcLayer->SetNextByIndex(psSelectInfo->offset);
1886
0
    }
1887
0
    if (m_nIteratedFeatures < 0)
1888
0
        m_nIteratedFeatures = 0;
1889
1890
    /* -------------------------------------------------------------------- */
1891
    /*      Handle summary sets.                                            */
1892
    /* -------------------------------------------------------------------- */
1893
0
    if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD ||
1894
0
        psSelectInfo->query_mode == SWQM_DISTINCT_LIST)
1895
0
    {
1896
0
        m_nIteratedFeatures++;
1897
0
        return GetFeature(m_nNextIndexFID++);
1898
0
    }
1899
1900
0
    int bEvaluateSpatialFilter = MustEvaluateSpatialFilterOnGenSQL();
1901
1902
    /* -------------------------------------------------------------------- */
1903
    /*      Handle ordered sets.                                            */
1904
    /* -------------------------------------------------------------------- */
1905
0
    while (true)
1906
0
    {
1907
0
        std::unique_ptr<OGRFeature> poSrcFeat;
1908
0
        if (!m_anFIDIndex.empty())
1909
0
        {
1910
            /* --------------------------------------------------------------------
1911
             */
1912
            /*      Are we running in sorted mode?  If so, run the fid through
1913
             */
1914
            /*      the index. */
1915
            /* --------------------------------------------------------------------
1916
             */
1917
1918
0
            if (m_nNextIndexFID >= static_cast<GIntBig>(m_anFIDIndex.size()))
1919
0
                return nullptr;
1920
1921
0
            poSrcFeat.reset(m_poSrcLayer->GetFeature(
1922
0
                m_anFIDIndex[static_cast<size_t>(m_nNextIndexFID)]));
1923
0
            m_nNextIndexFID++;
1924
0
        }
1925
0
        else
1926
0
        {
1927
0
            poSrcFeat.reset(m_poSrcLayer->GetNextFeature());
1928
0
        }
1929
1930
0
        if (poSrcFeat == nullptr)
1931
0
            return nullptr;
1932
1933
0
        auto poFeature = TranslateFeature(std::move(poSrcFeat));
1934
0
        if (poFeature == nullptr)
1935
0
            return nullptr;
1936
1937
0
        if ((m_poAttrQuery == nullptr ||
1938
0
             m_poAttrQuery->Evaluate(poFeature.get())) &&
1939
0
            (!bEvaluateSpatialFilter ||
1940
0
             FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))))
1941
0
        {
1942
0
            m_nIteratedFeatures++;
1943
0
            return poFeature.release();
1944
0
        }
1945
0
    }
1946
0
}
1947
1948
/************************************************************************/
1949
/*                             GetFeature()                             */
1950
/************************************************************************/
1951
1952
OGRFeature *OGRGenSQLResultsLayer::GetFeature(GIntBig nFID)
1953
1954
0
{
1955
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
1956
1957
0
    CreateOrderByIndex();
1958
1959
    /* -------------------------------------------------------------------- */
1960
    /*      Handle request for summary record.                              */
1961
    /* -------------------------------------------------------------------- */
1962
0
    if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD)
1963
0
    {
1964
0
        if (!PrepareSummary() || nFID != 0 || !m_poSummaryFeature)
1965
0
            return nullptr;
1966
0
        else
1967
0
            return m_poSummaryFeature->Clone();
1968
0
    }
1969
1970
    /* -------------------------------------------------------------------- */
1971
    /*      Handle request for distinct list record.                        */
1972
    /* -------------------------------------------------------------------- */
1973
0
    if (psSelectInfo->query_mode == SWQM_DISTINCT_LIST)
1974
0
    {
1975
0
        if (!PrepareSummary())
1976
0
            return nullptr;
1977
1978
0
        if (psSelectInfo->column_summary.empty())
1979
0
            return nullptr;
1980
1981
0
        swq_summary &oSummary = psSelectInfo->column_summary[0];
1982
0
        if (psSelectInfo->order_specs == 0)
1983
0
        {
1984
0
            if (nFID < 0 || nFID >= static_cast<GIntBig>(
1985
0
                                        oSummary.oVectorDistinctValues.size()))
1986
0
            {
1987
0
                return nullptr;
1988
0
            }
1989
0
            const size_t nIdx = static_cast<size_t>(nFID);
1990
0
            if (oSummary.oVectorDistinctValues[nIdx] != SZ_OGR_NULL)
1991
0
            {
1992
0
                m_poSummaryFeature->SetField(
1993
0
                    0, oSummary.oVectorDistinctValues[nIdx].c_str());
1994
0
            }
1995
0
            else
1996
0
                m_poSummaryFeature->SetFieldNull(0);
1997
0
        }
1998
0
        else
1999
0
        {
2000
0
            if (m_aosDistinctList.empty())
2001
0
            {
2002
0
                std::set<CPLString, swq_summary::Comparator>::const_iterator
2003
0
                    oIter = oSummary.oSetDistinctValues.begin();
2004
0
                std::set<CPLString, swq_summary::Comparator>::const_iterator
2005
0
                    oEnd = oSummary.oSetDistinctValues.end();
2006
0
                try
2007
0
                {
2008
0
                    m_aosDistinctList.reserve(
2009
0
                        oSummary.oSetDistinctValues.size());
2010
0
                    for (; oIter != oEnd; ++oIter)
2011
0
                    {
2012
0
                        m_aosDistinctList.push_back(*oIter);
2013
0
                    }
2014
0
                }
2015
0
                catch (std::bad_alloc &)
2016
0
                {
2017
0
                    return nullptr;
2018
0
                }
2019
0
                oSummary.oSetDistinctValues.clear();
2020
0
            }
2021
2022
0
            if (nFID < 0 ||
2023
0
                nFID >= static_cast<GIntBig>(m_aosDistinctList.size()))
2024
0
                return nullptr;
2025
2026
0
            const size_t nIdx = static_cast<size_t>(nFID);
2027
0
            if (m_aosDistinctList[nIdx] != SZ_OGR_NULL)
2028
0
                m_poSummaryFeature->SetField(0,
2029
0
                                             m_aosDistinctList[nIdx].c_str());
2030
0
            else
2031
0
                m_poSummaryFeature->SetFieldNull(0);
2032
0
        }
2033
2034
0
        m_poSummaryFeature->SetFID(nFID);
2035
2036
0
        return m_poSummaryFeature->Clone();
2037
0
    }
2038
2039
    /* -------------------------------------------------------------------- */
2040
    /*      Handle request for random record.                               */
2041
    /* -------------------------------------------------------------------- */
2042
0
    auto poSrcFeature =
2043
0
        std::unique_ptr<OGRFeature>(m_poSrcLayer->GetFeature(nFID));
2044
0
    if (poSrcFeature == nullptr)
2045
0
        return nullptr;
2046
2047
0
    return TranslateFeature(std::move(poSrcFeature)).release();
2048
0
}
2049
2050
/************************************************************************/
2051
/*                          GetSpatialFilter()                          */
2052
/************************************************************************/
2053
2054
OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter()
2055
2056
0
{
2057
0
    return nullptr;
2058
0
}
2059
2060
/************************************************************************/
2061
/*                            GetLayerDefn()                            */
2062
/************************************************************************/
2063
2064
const OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn() const
2065
2066
0
{
2067
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
2068
0
    if (psSelectInfo->query_mode == SWQM_SUMMARY_RECORD && !m_poSummaryFeature)
2069
0
    {
2070
        // Run PrepareSummary() is we have a COUNT column so as to be
2071
        // able to downcast it from OFTInteger64 to OFTInteger
2072
0
        for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
2073
0
        {
2074
0
            swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
2075
0
            if (psColDef->col_func == SWQCF_COUNT)
2076
0
            {
2077
0
                PrepareSummary();
2078
0
                break;
2079
0
            }
2080
0
        }
2081
0
    }
2082
2083
0
    return m_poDefn;
2084
0
}
2085
2086
/************************************************************************/
2087
/*                          FreeIndexFields()                           */
2088
/************************************************************************/
2089
2090
void OGRGenSQLResultsLayer::FreeIndexFields(OGRField *pasIndexFields,
2091
                                            size_t l_nIndexSize)
2092
0
{
2093
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
2094
0
    const int nOrderItems = psSelectInfo->order_specs;
2095
2096
    /* -------------------------------------------------------------------- */
2097
    /*      Free the key field values.                                      */
2098
    /* -------------------------------------------------------------------- */
2099
0
    for (int iKey = 0; iKey < nOrderItems; iKey++)
2100
0
    {
2101
0
        swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
2102
2103
0
        if (psKeyDef->field_index >= m_iFIDFieldIndex)
2104
0
        {
2105
0
            CPLAssert(psKeyDef->field_index <
2106
0
                      m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
2107
            /* warning: only special fields of type string should be deallocated
2108
             */
2109
0
            if (SpecialFieldTypes[psKeyDef->field_index - m_iFIDFieldIndex] ==
2110
0
                SWQ_STRING)
2111
0
            {
2112
0
                for (size_t i = 0; i < l_nIndexSize; i++)
2113
0
                {
2114
0
                    OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
2115
0
                    CPLFree(psField->String);
2116
0
                }
2117
0
            }
2118
0
            continue;
2119
0
        }
2120
2121
0
        OGRFieldDefn *poFDefn =
2122
0
            m_poSrcLayer->GetLayerDefn()->GetFieldDefn(psKeyDef->field_index);
2123
2124
0
        if (poFDefn->GetType() == OFTString)
2125
0
        {
2126
0
            for (size_t i = 0; i < l_nIndexSize; i++)
2127
0
            {
2128
0
                OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
2129
2130
0
                if (!OGR_RawField_IsUnset(psField) &&
2131
0
                    !OGR_RawField_IsNull(psField))
2132
0
                    CPLFree(psField->String);
2133
0
            }
2134
0
        }
2135
0
    }
2136
0
}
2137
2138
/************************************************************************/
2139
/*                          ReadIndexFields()                           */
2140
/************************************************************************/
2141
2142
void OGRGenSQLResultsLayer::ReadIndexFields(OGRFeature *poSrcFeat,
2143
                                            int nOrderItems,
2144
                                            OGRField *pasIndexFields)
2145
0
{
2146
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
2147
0
    for (int iKey = 0; iKey < nOrderItems; iKey++)
2148
0
    {
2149
0
        const swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
2150
0
        OGRField *psDstField = pasIndexFields + iKey;
2151
2152
0
        if (psKeyDef->field_index >= m_iFIDFieldIndex)
2153
0
        {
2154
0
            CPLAssert(psKeyDef->field_index <
2155
0
                      m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
2156
2157
0
            switch (SpecialFieldTypes[psKeyDef->field_index - m_iFIDFieldIndex])
2158
0
            {
2159
0
                case SWQ_INTEGER:
2160
0
                case SWQ_INTEGER64:
2161
                    // Yes, store Integer as Integer64.
2162
                    // This is consistent with the test in Compare()
2163
0
                    psDstField->Integer64 =
2164
0
                        poSrcFeat->GetFieldAsInteger64(psKeyDef->field_index);
2165
0
                    break;
2166
2167
0
                case SWQ_FLOAT:
2168
0
                    psDstField->Real =
2169
0
                        poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
2170
0
                    break;
2171
2172
0
                default:
2173
0
                    psDstField->String = CPLStrdup(
2174
0
                        poSrcFeat->GetFieldAsString(psKeyDef->field_index));
2175
0
                    break;
2176
0
            }
2177
2178
0
            continue;
2179
0
        }
2180
2181
0
        OGRFieldDefn *poFDefn =
2182
0
            m_poSrcLayer->GetLayerDefn()->GetFieldDefn(psKeyDef->field_index);
2183
2184
0
        OGRField *psSrcField = poSrcFeat->GetRawFieldRef(psKeyDef->field_index);
2185
2186
0
        if (poFDefn->GetType() == OFTInteger ||
2187
0
            poFDefn->GetType() == OFTInteger64 ||
2188
0
            poFDefn->GetType() == OFTReal || poFDefn->GetType() == OFTDate ||
2189
0
            poFDefn->GetType() == OFTTime || poFDefn->GetType() == OFTDateTime)
2190
0
            memcpy(psDstField, psSrcField, sizeof(OGRField));
2191
0
        else if (poFDefn->GetType() == OFTString)
2192
0
        {
2193
0
            if (poSrcFeat->IsFieldSetAndNotNull(psKeyDef->field_index))
2194
0
                psDstField->String = CPLStrdup(psSrcField->String);
2195
0
            else
2196
0
                memcpy(psDstField, psSrcField, sizeof(OGRField));
2197
0
        }
2198
0
    }
2199
0
}
2200
2201
/************************************************************************/
2202
/*                         CreateOrderByIndex()                         */
2203
/*                                                                      */
2204
/*      This method is responsible for creating an index providing      */
2205
/*      ordered access to the features according to the supplied        */
2206
/*      ORDER BY clauses.                                               */
2207
/*                                                                      */
2208
/*      This is accomplished by making one pass through all the         */
2209
/*      eligible source features, and capturing the order by fields     */
2210
/*      of all records in memory.  A quick sort is then applied to      */
2211
/*      this in memory copy of the order-by fields to create the        */
2212
/*      required index.                                                 */
2213
/*                                                                      */
2214
/*      Keeping all the key values in memory will *not* scale up to     */
2215
/*      very large input datasets.                                      */
2216
/************************************************************************/
2217
2218
void OGRGenSQLResultsLayer::CreateOrderByIndex()
2219
2220
0
{
2221
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
2222
0
    const int nOrderItems = psSelectInfo->order_specs;
2223
2224
0
    if (!(nOrderItems > 0 && psSelectInfo->query_mode == SWQM_RECORDSET))
2225
0
        return;
2226
2227
0
    if (m_bOrderByValid)
2228
0
        return;
2229
2230
0
    m_bOrderByValid = true;
2231
0
    m_anFIDIndex.clear();
2232
2233
0
    ResetReading();
2234
2235
    /* -------------------------------------------------------------------- */
2236
    /*      Optimize (memory-wise) ORDER BY ... LIMIT 1 [OFFSET 0] case.    */
2237
    /* -------------------------------------------------------------------- */
2238
0
    if (psSelectInfo->offset == 0 && psSelectInfo->limit == 1)
2239
0
    {
2240
0
        std::vector<OGRField> asCurrentFields(nOrderItems);
2241
0
        std::vector<OGRField> asBestFields(nOrderItems);
2242
0
        memset(asCurrentFields.data(), 0, sizeof(OGRField) * nOrderItems);
2243
0
        memset(asBestFields.data(), 0, sizeof(OGRField) * nOrderItems);
2244
0
        bool bFoundSrcFeature = false;
2245
0
        GIntBig nBestFID = 0;
2246
0
        for (auto &&poSrcFeat : *m_poSrcLayer)
2247
0
        {
2248
0
            ReadIndexFields(poSrcFeat.get(), nOrderItems,
2249
0
                            asCurrentFields.data());
2250
0
            if (!bFoundSrcFeature ||
2251
0
                Compare(asCurrentFields.data(), asBestFields.data()) < 0)
2252
0
            {
2253
0
                bFoundSrcFeature = true;
2254
0
                nBestFID = poSrcFeat->GetFID();
2255
0
                FreeIndexFields(asBestFields.data(), 1);
2256
0
                memcpy(asBestFields.data(), asCurrentFields.data(),
2257
0
                       sizeof(OGRField) * nOrderItems);
2258
0
            }
2259
0
            else
2260
0
            {
2261
0
                FreeIndexFields(asCurrentFields.data(), 1);
2262
0
            }
2263
0
            memset(asCurrentFields.data(), 0, sizeof(OGRField) * nOrderItems);
2264
0
        }
2265
0
        FreeIndexFields(asBestFields.data(), 1);
2266
2267
0
        if (bFoundSrcFeature)
2268
0
        {
2269
0
            m_anFIDIndex.resize(1);
2270
0
            m_anFIDIndex[0] = nBestFID;
2271
0
        }
2272
0
        return;
2273
0
    }
2274
2275
    /* -------------------------------------------------------------------- */
2276
    /*      Allocate set of key values, and the output index.               */
2277
    /* -------------------------------------------------------------------- */
2278
0
    size_t nFeaturesAlloc = 100;
2279
0
    size_t nIndexSize = 0;
2280
0
    std::vector<OGRField> asIndexFields(nOrderItems * nFeaturesAlloc);
2281
0
    memset(asIndexFields.data(), 0,
2282
0
           sizeof(OGRField) * nOrderItems * nFeaturesAlloc);
2283
0
    std::vector<GIntBig> anFIDList;
2284
2285
    // Frees nIndexSize rows of asIndexFields
2286
0
    struct IndexFieldsFreer
2287
0
    {
2288
0
        OGRGenSQLResultsLayer &m_oLayer;
2289
0
        std::vector<OGRField> &m_asIndexFields;
2290
0
        size_t &m_nIndexSize;
2291
2292
0
        IndexFieldsFreer(OGRGenSQLResultsLayer &poLayerIn,
2293
0
                         std::vector<OGRField> &asIndexFieldsIn,
2294
0
                         size_t &nIndexSizeIn)
2295
0
            : m_oLayer(poLayerIn), m_asIndexFields(asIndexFieldsIn),
2296
0
              m_nIndexSize(nIndexSizeIn)
2297
0
        {
2298
0
        }
2299
2300
0
        ~IndexFieldsFreer()
2301
0
        {
2302
0
            m_oLayer.FreeIndexFields(m_asIndexFields.data(), m_nIndexSize);
2303
0
        }
2304
2305
0
        IndexFieldsFreer(const IndexFieldsFreer &) = delete;
2306
0
        IndexFieldsFreer &operator=(const IndexFieldsFreer &) = delete;
2307
0
    };
2308
2309
0
    IndexFieldsFreer oIndexFieldsFreer(*this, asIndexFields, nIndexSize);
2310
2311
    /* -------------------------------------------------------------------- */
2312
    /*      Read in all the key values.                                     */
2313
    /* -------------------------------------------------------------------- */
2314
2315
0
    for (auto &&poSrcFeat : *m_poSrcLayer)
2316
0
    {
2317
0
        if (nIndexSize == nFeaturesAlloc)
2318
0
        {
2319
0
            const uint64_t nNewFeaturesAlloc64 =
2320
0
                static_cast<uint64_t>(nFeaturesAlloc) + nFeaturesAlloc / 3;
2321
#if SIZEOF_SIZE_T == 4
2322
            if (static_cast<size_t>(nNewFeaturesAlloc64) !=
2323
                    nNewFeaturesAlloc64 ||
2324
                static_cast<size_t>(sizeof(OGRField) * nOrderItems *
2325
                                    nNewFeaturesAlloc64) !=
2326
                    static_cast<uint64_t>(sizeof(OGRField)) * nOrderItems *
2327
                        nNewFeaturesAlloc64)
2328
            {
2329
                CPLError(CE_Failure, CPLE_AppDefined,
2330
                         "Cannot allocate pasIndexFields");
2331
                return;
2332
            }
2333
#endif
2334
0
            const size_t nNewFeaturesAlloc =
2335
0
                static_cast<size_t>(nNewFeaturesAlloc64);
2336
2337
0
            try
2338
0
            {
2339
0
                asIndexFields.resize(nOrderItems * nNewFeaturesAlloc);
2340
0
                anFIDList.reserve(nNewFeaturesAlloc);
2341
0
            }
2342
0
            catch (const std::bad_alloc &)
2343
0
            {
2344
0
                CPLError(CE_Failure, CPLE_OutOfMemory,
2345
0
                         "CreateOrderByIndex(): out of memory");
2346
0
                return;
2347
0
            }
2348
2349
0
            memset(asIndexFields.data() + nFeaturesAlloc * nOrderItems, 0,
2350
0
                   sizeof(OGRField) * nOrderItems *
2351
0
                       (nNewFeaturesAlloc - nFeaturesAlloc));
2352
2353
0
            nFeaturesAlloc = nNewFeaturesAlloc;
2354
0
        }
2355
2356
0
        ReadIndexFields(poSrcFeat.get(), nOrderItems,
2357
0
                        asIndexFields.data() + nIndexSize * nOrderItems);
2358
2359
0
        anFIDList.push_back(poSrcFeat->GetFID());
2360
2361
0
        nIndexSize++;
2362
0
    }
2363
2364
    // CPLDebug("GenSQL", "CreateOrderByIndex() = %zu features", nIndexSize);
2365
2366
    /* -------------------------------------------------------------------- */
2367
    /*      Initialize m_anFIDIndex                                         */
2368
    /* -------------------------------------------------------------------- */
2369
0
    try
2370
0
    {
2371
0
        m_anFIDIndex.reserve(nIndexSize);
2372
0
    }
2373
0
    catch (const std::bad_alloc &)
2374
0
    {
2375
0
        CPLError(CE_Failure, CPLE_OutOfMemory,
2376
0
                 "CreateOrderByIndex(): out of memory");
2377
0
        return;
2378
0
    }
2379
0
    for (size_t i = 0; i < nIndexSize; i++)
2380
0
        m_anFIDIndex.push_back(static_cast<GIntBig>(i));
2381
2382
    /* -------------------------------------------------------------------- */
2383
    /*      Quick sort the records.                                         */
2384
    /* -------------------------------------------------------------------- */
2385
2386
0
    GIntBig *panMerged = static_cast<GIntBig *>(
2387
0
        VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nIndexSize));
2388
0
    if (panMerged == nullptr)
2389
0
    {
2390
0
        m_anFIDIndex.clear();
2391
0
        return;
2392
0
    }
2393
2394
    // Note: this merge sort is slightly faster than std::sort()
2395
0
    SortIndexSection(asIndexFields.data(), panMerged, 0, nIndexSize);
2396
0
    VSIFree(panMerged);
2397
2398
    /* -------------------------------------------------------------------- */
2399
    /*      Rework the FID map to map to real FIDs.                         */
2400
    /* -------------------------------------------------------------------- */
2401
0
    bool bAlreadySorted = true;
2402
0
    for (size_t i = 0; i < nIndexSize; i++)
2403
0
    {
2404
0
        if (m_anFIDIndex[i] != static_cast<GIntBig>(i))
2405
0
            bAlreadySorted = false;
2406
0
        m_anFIDIndex[i] = anFIDList[static_cast<size_t>(m_anFIDIndex[i])];
2407
0
    }
2408
2409
    /* If it is already sorted, then free than m_anFIDIndex array */
2410
    /* so that GetNextFeature() can call a sequential GetNextFeature() */
2411
    /* on the source array. Very useful for layers where random access */
2412
    /* is slow. */
2413
    /* Use case: the GML result of a WFS GetFeature with a SORTBY */
2414
0
    if (bAlreadySorted)
2415
0
    {
2416
0
        m_anFIDIndex.clear();
2417
0
    }
2418
2419
0
    ResetReading();
2420
0
}
2421
2422
/************************************************************************/
2423
/*                          SortIndexSection()                          */
2424
/*                                                                      */
2425
/*      Sort the records in a section of the index.                     */
2426
/************************************************************************/
2427
2428
void OGRGenSQLResultsLayer::SortIndexSection(const OGRField *pasIndexFields,
2429
                                             GIntBig *panMerged, size_t nStart,
2430
                                             size_t nEntries)
2431
2432
0
{
2433
0
    if (nEntries < 2)
2434
0
        return;
2435
2436
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
2437
0
    const int nOrderItems = psSelectInfo->order_specs;
2438
2439
0
    size_t nFirstGroup = nEntries / 2;
2440
0
    size_t nFirstStart = nStart;
2441
0
    size_t nSecondGroup = nEntries - nFirstGroup;
2442
0
    size_t nSecondStart = nStart + nFirstGroup;
2443
2444
0
    SortIndexSection(pasIndexFields, panMerged, nFirstStart, nFirstGroup);
2445
0
    SortIndexSection(pasIndexFields, panMerged, nSecondStart, nSecondGroup);
2446
2447
0
    for (size_t iMerge = 0; iMerge < nEntries; ++iMerge)
2448
0
    {
2449
0
        int nResult = 0;
2450
2451
0
        if (nFirstGroup == 0)
2452
0
            nResult = 1;
2453
0
        else if (nSecondGroup == 0)
2454
0
            nResult = -1;
2455
0
        else
2456
0
            nResult = Compare(
2457
0
                pasIndexFields + m_anFIDIndex[nFirstStart] * nOrderItems,
2458
0
                pasIndexFields + m_anFIDIndex[nSecondStart] * nOrderItems);
2459
2460
0
        if (nResult > 0)
2461
0
        {
2462
0
            panMerged[iMerge] = m_anFIDIndex[nSecondStart];
2463
0
            nSecondStart++;
2464
0
            nSecondGroup--;
2465
0
        }
2466
0
        else
2467
0
        {
2468
0
            panMerged[iMerge] = m_anFIDIndex[nFirstStart];
2469
0
            nFirstStart++;
2470
0
            nFirstGroup--;
2471
0
        }
2472
0
    }
2473
2474
    /* Copy the merge list back into the main index */
2475
0
    memcpy(m_anFIDIndex.data() + nStart, panMerged, sizeof(GIntBig) * nEntries);
2476
0
}
2477
2478
/************************************************************************/
2479
/*                          ComparePrimitive()                          */
2480
/************************************************************************/
2481
2482
template <class T> static inline int ComparePrimitive(const T &a, const T &b)
2483
0
{
2484
0
    if (a < b)
2485
0
        return -1;
2486
0
    if (a > b)
2487
0
        return 1;
2488
0
    return 0;
2489
0
}
Unexecuted instantiation: ogr_gensql.cpp:int ComparePrimitive<long long>(long long const&, long long const&)
Unexecuted instantiation: ogr_gensql.cpp:int ComparePrimitive<double>(double const&, double const&)
Unexecuted instantiation: ogr_gensql.cpp:int ComparePrimitive<int>(int const&, int const&)
2490
2491
/************************************************************************/
2492
/*                              Compare()                               */
2493
/************************************************************************/
2494
2495
int OGRGenSQLResultsLayer::Compare(const OGRField *pasFirstTuple,
2496
                                   const OGRField *pasSecondTuple)
2497
2498
0
{
2499
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
2500
0
    int nResult = 0, iKey;
2501
2502
0
    for (iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++)
2503
0
    {
2504
0
        swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
2505
0
        OGRFieldDefn *poFDefn = nullptr;
2506
2507
0
        if (psKeyDef->field_index >= m_iFIDFieldIndex)
2508
0
            poFDefn = nullptr;
2509
0
        else
2510
0
            poFDefn = m_poSrcLayer->GetLayerDefn()->GetFieldDefn(
2511
0
                psKeyDef->field_index);
2512
2513
0
        if (OGR_RawField_IsUnset(&pasFirstTuple[iKey]) ||
2514
0
            OGR_RawField_IsNull(&pasFirstTuple[iKey]))
2515
0
        {
2516
0
            if (OGR_RawField_IsUnset(&pasSecondTuple[iKey]) ||
2517
0
                OGR_RawField_IsNull(&pasSecondTuple[iKey]))
2518
0
                nResult = 0;
2519
0
            else
2520
0
                nResult = -1;
2521
0
        }
2522
0
        else if (OGR_RawField_IsUnset(&pasSecondTuple[iKey]) ||
2523
0
                 OGR_RawField_IsNull(&pasSecondTuple[iKey]))
2524
0
        {
2525
0
            nResult = 1;
2526
0
        }
2527
0
        else if (poFDefn == nullptr)
2528
0
        {
2529
0
            CPLAssert(psKeyDef->field_index <
2530
0
                      m_iFIDFieldIndex + SPECIAL_FIELD_COUNT);
2531
0
            switch (SpecialFieldTypes[psKeyDef->field_index - m_iFIDFieldIndex])
2532
0
            {
2533
0
                case SWQ_INTEGER:
2534
                    // Yes, read Integer in Integer64.
2535
                    // This is consistent with what is done ReadIndexFields()
2536
0
                case SWQ_INTEGER64:
2537
0
                    nResult = ComparePrimitive(pasFirstTuple[iKey].Integer64,
2538
0
                                               pasSecondTuple[iKey].Integer64);
2539
0
                    break;
2540
0
                case SWQ_FLOAT:
2541
0
                    nResult = ComparePrimitive(pasFirstTuple[iKey].Real,
2542
0
                                               pasSecondTuple[iKey].Real);
2543
0
                    break;
2544
0
                case SWQ_STRING:
2545
0
                    nResult = strcmp(pasFirstTuple[iKey].String,
2546
0
                                     pasSecondTuple[iKey].String);
2547
0
                    break;
2548
2549
0
                default:
2550
0
                    CPLAssert(false);
2551
0
                    nResult = 0;
2552
0
            }
2553
0
        }
2554
0
        else if (poFDefn->GetType() == OFTInteger)
2555
0
        {
2556
0
            nResult = ComparePrimitive(pasFirstTuple[iKey].Integer,
2557
0
                                       pasSecondTuple[iKey].Integer);
2558
0
        }
2559
0
        else if (poFDefn->GetType() == OFTInteger64)
2560
0
        {
2561
0
            nResult = ComparePrimitive(pasFirstTuple[iKey].Integer64,
2562
0
                                       pasSecondTuple[iKey].Integer64);
2563
0
        }
2564
0
        else if (poFDefn->GetType() == OFTString)
2565
0
        {
2566
0
            nResult =
2567
0
                strcmp(pasFirstTuple[iKey].String, pasSecondTuple[iKey].String);
2568
0
        }
2569
0
        else if (poFDefn->GetType() == OFTReal)
2570
0
        {
2571
0
            nResult = ComparePrimitive(pasFirstTuple[iKey].Real,
2572
0
                                       pasSecondTuple[iKey].Real);
2573
0
        }
2574
0
        else if (poFDefn->GetType() == OFTDate ||
2575
0
                 poFDefn->GetType() == OFTTime ||
2576
0
                 poFDefn->GetType() == OFTDateTime)
2577
0
        {
2578
0
            nResult =
2579
0
                OGRCompareDate(&pasFirstTuple[iKey], &pasSecondTuple[iKey]);
2580
0
        }
2581
2582
0
        if (!(psKeyDef->ascending_flag))
2583
0
            nResult *= -1;
2584
0
    }
2585
2586
0
    return nResult;
2587
0
}
2588
2589
/************************************************************************/
2590
/*                         AddFieldDefnToSet()                          */
2591
/************************************************************************/
2592
2593
void OGRGenSQLResultsLayer::AddFieldDefnToSet(int iTable, int iColumn,
2594
                                              CPLHashSet *hSet)
2595
0
{
2596
0
    if (iTable != -1)
2597
0
    {
2598
0
        OGRLayer *poLayer = m_apoTableLayers[iTable];
2599
0
        const auto poLayerDefn = poLayer->GetLayerDefn();
2600
0
        const int nFieldCount = poLayerDefn->GetFieldCount();
2601
0
        if (iColumn == -1)
2602
0
        {
2603
0
            for (int i = 0; i < nFieldCount; ++i)
2604
0
            {
2605
0
                OGRFieldDefn *poFDefn = poLayerDefn->GetFieldDefn(i);
2606
0
                CPLHashSetInsert(hSet, poFDefn);
2607
0
            }
2608
2609
0
            const int nGeomFieldCount = poLayerDefn->GetGeomFieldCount();
2610
0
            for (int i = 0; i < nGeomFieldCount; ++i)
2611
0
            {
2612
0
                OGRGeomFieldDefn *poFDefn = poLayerDefn->GetGeomFieldDefn(i);
2613
0
                CPLHashSetInsert(hSet, poFDefn);
2614
0
            }
2615
0
        }
2616
0
        else
2617
0
        {
2618
0
            if (iColumn < nFieldCount)
2619
0
            {
2620
0
                OGRFieldDefn *poFDefn = poLayerDefn->GetFieldDefn(iColumn);
2621
0
                CPLHashSetInsert(hSet, poFDefn);
2622
0
            }
2623
0
            else if (iColumn == nFieldCount + SPF_OGR_GEOMETRY ||
2624
0
                     iColumn == nFieldCount + SPF_OGR_GEOM_WKT ||
2625
0
                     iColumn == nFieldCount + SPF_OGR_GEOM_AREA)
2626
0
            {
2627
0
                auto poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(0);
2628
0
                CPLHashSetInsert(hSet, poSrcGFDefn);
2629
0
            }
2630
0
            else if (IS_GEOM_FIELD_INDEX(poLayerDefn, iColumn))
2631
0
            {
2632
0
                const int iSrcGeomField =
2633
0
                    ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(poLayerDefn, iColumn);
2634
0
                auto poSrcGFDefn = poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
2635
0
                CPLHashSetInsert(hSet, poSrcGFDefn);
2636
0
            }
2637
0
        }
2638
0
    }
2639
0
}
2640
2641
/************************************************************************/
2642
/*                    ExploreExprForIgnoredFields()                     */
2643
/************************************************************************/
2644
2645
void OGRGenSQLResultsLayer::ExploreExprForIgnoredFields(swq_expr_node *expr,
2646
                                                        CPLHashSet *hSet)
2647
0
{
2648
0
    if (expr->eNodeType == SNT_COLUMN)
2649
0
    {
2650
0
        AddFieldDefnToSet(expr->table_index, expr->field_index, hSet);
2651
0
    }
2652
0
    else if (expr->eNodeType == SNT_OPERATION)
2653
0
    {
2654
0
        for (int i = 0; i < expr->nSubExprCount; i++)
2655
0
            ExploreExprForIgnoredFields(expr->papoSubExpr[i], hSet);
2656
0
    }
2657
0
}
2658
2659
/************************************************************************/
2660
/*                      FindAndSetIgnoredFields()                       */
2661
/************************************************************************/
2662
2663
void OGRGenSQLResultsLayer::FindAndSetIgnoredFields()
2664
0
{
2665
0
    swq_select *psSelectInfo = m_pSelectInfo.get();
2666
0
    CPLHashSet *hSet =
2667
0
        CPLHashSetNew(CPLHashSetHashPointer, CPLHashSetEqualPointer, nullptr);
2668
2669
    /* -------------------------------------------------------------------- */
2670
    /*      1st phase : explore the whole select infos to determine which   */
2671
    /*      source fields are used                                          */
2672
    /* -------------------------------------------------------------------- */
2673
0
    for (int iField = 0; iField < psSelectInfo->result_columns(); iField++)
2674
0
    {
2675
0
        swq_col_def *psColDef = &psSelectInfo->column_defs[iField];
2676
0
        AddFieldDefnToSet(psColDef->table_index, psColDef->field_index, hSet);
2677
0
        if (psColDef->expr)
2678
0
            ExploreExprForIgnoredFields(psColDef->expr, hSet);
2679
0
    }
2680
2681
0
    if (psSelectInfo->where_expr)
2682
0
        ExploreExprForIgnoredFields(psSelectInfo->where_expr, hSet);
2683
2684
0
    for (int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++)
2685
0
    {
2686
0
        swq_join_def *psJoinDef = psSelectInfo->join_defs + iJoin;
2687
0
        ExploreExprForIgnoredFields(psJoinDef->poExpr, hSet);
2688
0
    }
2689
2690
0
    for (int iOrder = 0; iOrder < psSelectInfo->order_specs; iOrder++)
2691
0
    {
2692
0
        swq_order_def *psOrderDef = psSelectInfo->order_defs + iOrder;
2693
0
        AddFieldDefnToSet(psOrderDef->table_index, psOrderDef->field_index,
2694
0
                          hSet);
2695
0
    }
2696
2697
    /* -------------------------------------------------------------------- */
2698
    /*      2nd phase : now, we can exclude the unused fields               */
2699
    /* -------------------------------------------------------------------- */
2700
0
    for (int iTable = 0; iTable < psSelectInfo->table_count; iTable++)
2701
0
    {
2702
0
        OGRLayer *poLayer = m_apoTableLayers[iTable];
2703
0
        OGRFeatureDefn *poSrcFDefn = poLayer->GetLayerDefn();
2704
0
        char **papszIgnoredFields = nullptr;
2705
0
        const int nSrcFieldCount = poSrcFDefn->GetFieldCount();
2706
0
        for (int iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++)
2707
0
        {
2708
0
            OGRFieldDefn *poFDefn = poSrcFDefn->GetFieldDefn(iSrcField);
2709
0
            if (CPLHashSetLookup(hSet, poFDefn) == nullptr)
2710
0
            {
2711
0
                papszIgnoredFields =
2712
0
                    CSLAddString(papszIgnoredFields, poFDefn->GetNameRef());
2713
                // CPLDebug("OGR", "Adding %s to the list of ignored fields of
2714
                // layer %s",
2715
                //          poFDefn->GetNameRef(), poLayer->GetName());
2716
0
            }
2717
0
        }
2718
0
        if (!m_bSpatialFilterSetOnSourceLayer)
2719
0
        {
2720
0
            const int nSrcGeomFieldCount = poSrcFDefn->GetGeomFieldCount();
2721
0
            for (int iSrcField = 0; iSrcField < nSrcGeomFieldCount; iSrcField++)
2722
0
            {
2723
0
                OGRGeomFieldDefn *poFDefn =
2724
0
                    poSrcFDefn->GetGeomFieldDefn(iSrcField);
2725
0
                if (CPLHashSetLookup(hSet, poFDefn) == nullptr)
2726
0
                {
2727
0
                    papszIgnoredFields =
2728
0
                        CSLAddString(papszIgnoredFields, poFDefn->GetNameRef());
2729
                    // CPLDebug("OGR", "Adding %s to the list of ignored fields of
2730
                    // layer %s",
2731
                    //          poFDefn->GetNameRef(), poLayer->GetName());
2732
0
                }
2733
0
            }
2734
0
        }
2735
0
        poLayer->SetIgnoredFields(
2736
0
            const_cast<const char **>(papszIgnoredFields));
2737
0
        CSLDestroy(papszIgnoredFields);
2738
0
    }
2739
2740
0
    CPLHashSetDestroy(hSet);
2741
0
}
2742
2743
/************************************************************************/
2744
/*                       InvalidateOrderByIndex()                       */
2745
/************************************************************************/
2746
2747
void OGRGenSQLResultsLayer::InvalidateOrderByIndex()
2748
0
{
2749
0
    m_anFIDIndex.clear();
2750
0
    m_bOrderByValid = false;
2751
0
}
2752
2753
/************************************************************************/
2754
/*                         SetAttributeFilter()                         */
2755
/************************************************************************/
2756
2757
OGRErr OGRGenSQLResultsLayer::SetAttributeFilter(const char *pszAttributeFilter)
2758
0
{
2759
0
    const std::string osAdditionalWHERE =
2760
0
        pszAttributeFilter ? pszAttributeFilter : "";
2761
0
    std::string osWHERE;
2762
0
    if (!m_bForwardWhereToSourceLayer && !m_osInitialWHERE.empty())
2763
0
    {
2764
0
        if (!osAdditionalWHERE.empty())
2765
0
            osWHERE += '(';
2766
0
        osWHERE += m_osInitialWHERE;
2767
0
        if (!osAdditionalWHERE.empty())
2768
0
            osWHERE += ") AND (";
2769
0
    }
2770
0
    osWHERE += osAdditionalWHERE;
2771
0
    if (!m_bForwardWhereToSourceLayer && !m_osInitialWHERE.empty() &&
2772
0
        !osAdditionalWHERE.empty())
2773
0
    {
2774
0
        osWHERE += ')';
2775
0
    }
2776
0
    InvalidateOrderByIndex();
2777
0
    return OGRLayer::SetAttributeFilter(osWHERE.empty() ? nullptr
2778
0
                                                        : osWHERE.c_str());
2779
0
}
2780
2781
/************************************************************************/
2782
/*                         ISetSpatialFilter()                          */
2783
/************************************************************************/
2784
2785
OGRErr OGRGenSQLResultsLayer::ISetSpatialFilter(int iGeomField,
2786
                                                const OGRGeometry *poGeom)
2787
0
{
2788
0
    InvalidateOrderByIndex();
2789
0
    return OGRLayer::ISetSpatialFilter(iGeomField, poGeom);
2790
0
}
2791
2792
/************************************************************************/
2793
/*             OGRGenSQLResultsLayerArrowStreamPrivateData              */
2794
/************************************************************************/
2795
2796
// Structure whose instances are set on the ArrowArrayStream::private_data
2797
// member of the ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2798
struct OGRGenSQLResultsLayerArrowStreamPrivateData
2799
{
2800
    // Member shared with OGRLayer::m_poSharedArrowArrayStreamPrivateData
2801
    // If the layer pointed by poShared->poLayer is destroyed, before its
2802
    // destruction, it nullifies poShared->poLayer, which we can detect.
2803
    std::shared_ptr<OGRLayer::ArrowArrayStreamPrivateData> poShared{};
2804
2805
    // ArrowArrayStream to be used with poShared->poLayer
2806
    struct ArrowArrayStream *psSrcLayerStream = nullptr;
2807
2808
    // Original release() callback of the ArrowArrayStream passed to
2809
    // OGRGenSQLResultsLayer::GetArrowStream()
2810
    void (*release_backup)(struct ArrowArrayStream *) = nullptr;
2811
2812
    // Original private_data member of the ArrowArrayStream passed to
2813
    // OGRGenSQLResultsLayer::GetArrowStream()
2814
    void *private_data_backup = nullptr;
2815
2816
    // Set as the ArrowArrayStream::release callback member of the
2817
    // ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2818
    static void Release(struct ArrowArrayStream *self)
2819
0
    {
2820
0
        OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2821
0
            static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2822
0
                self->private_data);
2823
2824
        // Release source layer stream
2825
0
        if (psPrivateData->psSrcLayerStream->release)
2826
0
            psPrivateData->psSrcLayerStream->release(
2827
0
                psPrivateData->psSrcLayerStream);
2828
0
        CPLFree(psPrivateData->psSrcLayerStream);
2829
2830
        // Release ourselves using the base method
2831
0
        self->private_data = psPrivateData->private_data_backup;
2832
0
        self->release = psPrivateData->release_backup;
2833
0
        delete psPrivateData;
2834
0
        if (self->release)
2835
0
            self->release(self);
2836
0
    }
2837
2838
    // Set as the ArrowArrayStream::get_schema callback member of the
2839
    // ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2840
    static int GetSchema(struct ArrowArrayStream *self, struct ArrowSchema *out)
2841
0
    {
2842
0
        OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2843
0
            static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2844
0
                self->private_data);
2845
0
        auto poLayer = dynamic_cast<OGRGenSQLResultsLayer *>(
2846
0
            psPrivateData->poShared->m_poLayer);
2847
0
        if (!poLayer)
2848
0
        {
2849
0
            CPLError(
2850
0
                CE_Failure, CPLE_NotSupported,
2851
0
                "Calling get_schema() on a freed OGRLayer is not supported");
2852
0
            return EINVAL;
2853
0
        }
2854
0
        return poLayer->GetArrowSchemaForwarded(self, out);
2855
0
    }
2856
2857
    // Set as the ArrowArrayStream::get_next callback member of the
2858
    // ArrowArrayStream returned by OGRGenSQLResultsLayer::GetArrowStream()
2859
    static int GetNext(struct ArrowArrayStream *self, struct ArrowArray *out)
2860
0
    {
2861
0
        OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2862
0
            static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2863
0
                self->private_data);
2864
0
        auto poLayer = dynamic_cast<OGRGenSQLResultsLayer *>(
2865
0
            psPrivateData->poShared->m_poLayer);
2866
0
        if (!poLayer)
2867
0
        {
2868
0
            CPLError(CE_Failure, CPLE_NotSupported,
2869
0
                     "Calling get_next() on a freed OGRLayer is not supported");
2870
0
            return EINVAL;
2871
0
        }
2872
0
        return poLayer->GetNextArrowArrayForwarded(self, out);
2873
0
    }
2874
};
2875
2876
/************************************************************************/
2877
/*                           GetArrowStream()                           */
2878
/************************************************************************/
2879
2880
bool OGRGenSQLResultsLayer::GetArrowStream(struct ArrowArrayStream *out_stream,
2881
                                           CSLConstList papszOptions)
2882
0
{
2883
0
    if (!TestCapability(OLCFastGetArrowStream) ||
2884
0
        CPLTestBool(CPLGetConfigOption("OGR_GENSQL_STREAM_BASE_IMPL", "NO")))
2885
0
    {
2886
0
        CPLStringList aosOptions(papszOptions);
2887
0
        aosOptions.SetNameValue("OGR_GENSQL_STREAM_BASE_IMPL", "YES");
2888
0
        return OGRLayer::GetArrowStream(out_stream, aosOptions.List());
2889
0
    }
2890
2891
0
    const swq_select *psSelectInfo = m_pSelectInfo.get();
2892
0
    if (m_nIteratedFeatures != -1)
2893
0
    {
2894
0
        CPLError(CE_Failure, CPLE_AppDefined,
2895
0
                 "GetArrowStream() not supported on non-rewinded layer");
2896
0
        return false;
2897
0
    }
2898
0
    CPLStringList aosOptions(papszOptions);
2899
0
    if (psSelectInfo->limit > 0)
2900
0
    {
2901
0
        aosOptions.SetNameValue(
2902
0
            "MAX_FEATURES_IN_BATCH",
2903
0
            CPLSPrintf(CPL_FRMT_GIB,
2904
0
                       std::min(psSelectInfo->limit,
2905
0
                                CPLAtoGIntBig(aosOptions.FetchNameValueDef(
2906
0
                                    "MAX_FEATURES_IN_BATCH", "65536")))));
2907
0
    }
2908
0
    bool bRet = OGRLayer::GetArrowStream(out_stream, aosOptions.List());
2909
0
    if (bRet)
2910
0
    {
2911
0
        auto psSrcLayerStream = static_cast<struct ArrowArrayStream *>(
2912
0
            CPLMalloc(sizeof(ArrowArrayStream)));
2913
0
        if (m_poSrcLayer->GetArrowStream(psSrcLayerStream, aosOptions.List()))
2914
0
        {
2915
0
            auto psPrivateData =
2916
0
                new OGRGenSQLResultsLayerArrowStreamPrivateData;
2917
0
            CPLAssert(m_poSharedArrowArrayStreamPrivateData);
2918
0
            psPrivateData->poShared = m_poSharedArrowArrayStreamPrivateData;
2919
0
            psPrivateData->psSrcLayerStream = psSrcLayerStream;
2920
0
            psPrivateData->release_backup = out_stream->release;
2921
0
            psPrivateData->private_data_backup = out_stream->private_data;
2922
0
            out_stream->get_schema =
2923
0
                OGRGenSQLResultsLayerArrowStreamPrivateData::GetSchema;
2924
0
            out_stream->get_next =
2925
0
                OGRGenSQLResultsLayerArrowStreamPrivateData::GetNext;
2926
0
            out_stream->release =
2927
0
                OGRGenSQLResultsLayerArrowStreamPrivateData::Release;
2928
0
            out_stream->private_data = psPrivateData;
2929
0
        }
2930
0
        else
2931
0
        {
2932
0
            if (psSrcLayerStream->release)
2933
0
                psSrcLayerStream->release(psSrcLayerStream);
2934
0
            CPLFree(psSrcLayerStream);
2935
0
            if (out_stream->release)
2936
0
                out_stream->release(out_stream);
2937
0
            bRet = false;
2938
0
        }
2939
0
    }
2940
0
    return bRet;
2941
0
}
2942
2943
/************************************************************************/
2944
/*                           GetArrowSchema()                           */
2945
/************************************************************************/
2946
2947
int OGRGenSQLResultsLayer::GetArrowSchema(struct ArrowArrayStream *stream,
2948
                                          struct ArrowSchema *out_schema)
2949
0
{
2950
0
    if (m_aosArrowArrayStreamOptions.FetchNameValue(
2951
0
            "OGR_GENSQL_STREAM_BASE_IMPL") ||
2952
0
        !TestCapability(OLCFastGetArrowStream))
2953
0
    {
2954
0
        return OGRLayer::GetArrowSchema(stream, out_schema);
2955
0
    }
2956
2957
0
    return GetArrowSchemaForwarded(stream, out_schema);
2958
0
}
2959
2960
/************************************************************************/
2961
/*                      GetArrowSchemaForwarded()                       */
2962
/************************************************************************/
2963
2964
int OGRGenSQLResultsLayer::GetArrowSchemaForwarded(
2965
    struct ArrowArrayStream *stream, struct ArrowSchema *out_schema) const
2966
0
{
2967
0
    const swq_select *psSelectInfo = m_pSelectInfo.get();
2968
0
    OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
2969
0
        static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
2970
0
            stream->private_data);
2971
0
    int ret = m_poSrcLayer->GetArrowSchema(psPrivateData->psSrcLayerStream,
2972
0
                                           out_schema);
2973
0
    if (ret == 0)
2974
0
    {
2975
0
        struct ArrowSchema newSchema;
2976
0
        ret = OGRCloneArrowSchema(out_schema, &newSchema) ? 0 : EIO;
2977
0
        if (out_schema->release)
2978
0
            out_schema->release(out_schema);
2979
0
        if (ret == 0)
2980
0
        {
2981
0
            std::map<std::string, std::string> oMapSrcNameToRenamed;
2982
0
            for (std::size_t iField = 0;
2983
0
                 iField < psSelectInfo->column_defs.size(); iField++)
2984
0
            {
2985
0
                const swq_col_def *psColDef =
2986
0
                    &psSelectInfo->column_defs[iField];
2987
0
                CPLAssert(!psColDef->bHidden);
2988
0
                CPLAssert(psColDef->table_index >= 0);
2989
0
                CPLAssert(psColDef->col_func == SWQCF_NONE);
2990
2991
0
                const auto poLayerDefn =
2992
0
                    m_apoTableLayers[psColDef->table_index]->GetLayerDefn();
2993
0
                CPLAssert(poLayerDefn);
2994
2995
0
                if (psColDef->field_index >= 0 &&
2996
0
                    psColDef->field_index < poLayerDefn->GetFieldCount())
2997
0
                {
2998
0
                    const auto poSrcFDefn =
2999
0
                        poLayerDefn->GetFieldDefn(psColDef->field_index);
3000
0
                    if (psColDef->field_alias)
3001
0
                        oMapSrcNameToRenamed[poSrcFDefn->GetNameRef()] =
3002
0
                            psColDef->field_alias;
3003
0
                }
3004
0
                else if (IS_GEOM_FIELD_INDEX(poLayerDefn,
3005
0
                                             psColDef->field_index))
3006
0
                {
3007
0
                    const int iSrcGeomField =
3008
0
                        ALL_FIELD_INDEX_TO_GEOM_FIELD_INDEX(
3009
0
                            poLayerDefn, psColDef->field_index);
3010
0
                    const auto poSrcGFDefn =
3011
0
                        poLayerDefn->GetGeomFieldDefn(iSrcGeomField);
3012
0
                    if (psColDef->field_alias)
3013
0
                        oMapSrcNameToRenamed[poSrcGFDefn->GetNameRef()] =
3014
0
                            psColDef->field_alias;
3015
0
                }
3016
0
            }
3017
3018
0
            for (int i = 0; i < newSchema.n_children; ++i)
3019
0
            {
3020
0
                const auto oIter =
3021
0
                    oMapSrcNameToRenamed.find(newSchema.children[i]->name);
3022
0
                if (oIter != oMapSrcNameToRenamed.end())
3023
0
                {
3024
0
                    CPLFree(const_cast<char *>(newSchema.children[i]->name));
3025
0
                    newSchema.children[i]->name =
3026
0
                        CPLStrdup(oIter->second.c_str());
3027
0
                }
3028
0
            }
3029
3030
0
            memcpy(out_schema, &newSchema, sizeof(newSchema));
3031
0
        }
3032
0
    }
3033
0
    return ret;
3034
0
}
3035
3036
/************************************************************************/
3037
/*                         GetNextArrowArray()                          */
3038
/************************************************************************/
3039
3040
int OGRGenSQLResultsLayer::GetNextArrowArray(struct ArrowArrayStream *stream,
3041
                                             struct ArrowArray *out_array)
3042
0
{
3043
0
    if (m_aosArrowArrayStreamOptions.FetchNameValue(
3044
0
            "OGR_GENSQL_STREAM_BASE_IMPL") ||
3045
0
        !TestCapability(OLCFastGetArrowStream))
3046
0
    {
3047
0
        return OGRLayer::GetNextArrowArray(stream, out_array);
3048
0
    }
3049
3050
0
    return GetNextArrowArrayForwarded(stream, out_array);
3051
0
}
3052
3053
/************************************************************************/
3054
/*                     GetNextArrowArrayForwarded()                     */
3055
/************************************************************************/
3056
3057
int OGRGenSQLResultsLayer::GetNextArrowArrayForwarded(
3058
    struct ArrowArrayStream *stream, struct ArrowArray *out_array)
3059
0
{
3060
0
    const swq_select *psSelectInfo = m_pSelectInfo.get();
3061
0
    if (psSelectInfo->limit >= 0 && m_nIteratedFeatures >= psSelectInfo->limit)
3062
0
    {
3063
0
        memset(out_array, 0, sizeof(*out_array));
3064
0
        return 0;
3065
0
    }
3066
3067
0
    OGRGenSQLResultsLayerArrowStreamPrivateData *psPrivateData =
3068
0
        static_cast<OGRGenSQLResultsLayerArrowStreamPrivateData *>(
3069
0
            stream->private_data);
3070
0
    const int ret = m_poSrcLayer->GetNextArrowArray(
3071
0
        psPrivateData->psSrcLayerStream, out_array);
3072
0
    if (ret == 0 && psSelectInfo->limit >= 0)
3073
0
    {
3074
0
        if (m_nIteratedFeatures < 0)
3075
0
            m_nIteratedFeatures = 0;
3076
0
        m_nIteratedFeatures += out_array->length;
3077
0
        if (m_nIteratedFeatures > psSelectInfo->limit)
3078
0
        {
3079
0
            out_array->length -= m_nIteratedFeatures - psSelectInfo->limit;
3080
0
            for (int i = 0; i < out_array->n_children; ++i)
3081
0
            {
3082
0
                out_array->children[i]->length -=
3083
0
                    m_nIteratedFeatures - psSelectInfo->limit;
3084
0
            }
3085
0
        }
3086
0
    }
3087
0
    return ret;
3088
0
}
3089
3090
//! @endcond