Coverage Report

Created: 2025-11-16 06:25

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