Coverage Report

Created: 2025-08-28 06:57

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