Coverage Report

Created: 2025-06-13 06:29

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