Coverage Report

Created: 2026-02-14 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/adbc/ogr_adbc.h
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL
4
 * Purpose:  Arrow Database Connectivity driver
5
 * Author:   Even Rouault, <even dot rouault at spatialys.com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#ifndef OGR_ADBC_INCLUDED
14
#define OGR_ADBC_INCLUDED
15
16
#include "gdal_priv.h"
17
#include "ogrsf_frmts.h"
18
#include "ogrlayerarrow.h"
19
20
#include "ogr_adbc_internal.h"
21
22
/************************************************************************/
23
/*                OGRArrowArrayToOGRFeatureAdapterLayer                 */
24
/************************************************************************/
25
26
class OGRArrowArrayToOGRFeatureAdapterLayer final : public OGRLayer
27
{
28
    friend class OGRADBCLayer;
29
    OGRFeatureDefn *m_poLayerDefn = nullptr;
30
    std::vector<std::unique_ptr<OGRFeature>> m_apoFeatures{};
31
32
    CPL_DISALLOW_COPY_ASSIGN(OGRArrowArrayToOGRFeatureAdapterLayer)
33
34
  public:
35
    explicit OGRArrowArrayToOGRFeatureAdapterLayer(const char *pszName)
36
0
    {
37
0
        m_poLayerDefn = new OGRFeatureDefn(pszName);
38
0
        m_poLayerDefn->SetGeomType(wkbNone);
39
0
        m_poLayerDefn->Reference();
40
0
    }
41
42
    ~OGRArrowArrayToOGRFeatureAdapterLayer() override;
43
44
    using OGRLayer::GetLayerDefn;
45
46
    const OGRFeatureDefn *GetLayerDefn() const override
47
0
    {
48
0
        return m_poLayerDefn;
49
0
    }
50
51
    void ResetReading() override
52
0
    {
53
0
    }
54
55
    OGRFeature *GetNextFeature() override
56
0
    {
57
0
        return nullptr;
58
0
    }
59
60
    int TestCapability(const char *pszCap) const override
61
0
    {
62
0
        return EQUAL(pszCap, OLCCreateField) ||
63
0
               EQUAL(pszCap, OLCSequentialWrite);
64
0
    }
65
66
    OGRErr CreateField(const OGRFieldDefn *poFieldDefn, int) override
67
0
    {
68
0
        m_poLayerDefn->AddFieldDefn(poFieldDefn);
69
0
        return OGRERR_NONE;
70
0
    }
71
72
    OGRErr CreateGeomField(const OGRGeomFieldDefn *poGeomFieldDefn,
73
                           int) override
74
0
    {
75
0
        m_poLayerDefn->AddGeomFieldDefn(poGeomFieldDefn);
76
0
        return OGRERR_NONE;
77
0
    }
78
79
    OGRErr ICreateFeature(OGRFeature *poFeature) override
80
0
    {
81
0
        m_apoFeatures.emplace_back(
82
0
            std::unique_ptr<OGRFeature>(poFeature->Clone()));
83
0
        return OGRERR_NONE;
84
0
    }
85
};
86
87
/************************************************************************/
88
/*                             OGRADBCLayer                             */
89
/************************************************************************/
90
91
class OGRADBCDataset;
92
93
class OGRADBCLayer /* non final */ : public OGRLayer,
94
                                     public OGRGetNextFeatureThroughRaw<
95
                                         OGRADBCLayer>
96
{
97
  public:
98
    //! Describe the bbox column of a geometry column
99
    struct GeomColBBOX
100
    {
101
        std::string osXMin{};  // empty if no bbox column
102
        std::string osYMin{};
103
        std::string osXMax{};
104
        std::string osYMax{};
105
    };
106
107
  protected:
108
    friend class OGRADBCDataset;
109
110
    OGRADBCDataset *m_poDS = nullptr;
111
    const std::string m_osBaseStatement{};    // as provided by user
112
    std::string m_osModifiedBaseStatement{};  // above tuned to use ST_AsWKB()
113
    std::string m_osModifiedSelect{};         // SELECT part of above
114
    std::string m_osAttributeFilter{};
115
    std::unique_ptr<AdbcStatement> m_statement{};
116
    std::unique_ptr<OGRArrowArrayToOGRFeatureAdapterLayer> m_poAdapterLayer{};
117
    std::unique_ptr<OGRArrowArrayStream> m_stream{};
118
    bool m_bInternalUse = false;
119
    bool m_bLayerDefinitionError = false;
120
121
    struct ArrowSchema m_schema{};
122
123
    bool m_bEOF = false;
124
    size_t m_nIdx = 0;
125
    GIntBig m_nFeatureID = 0;
126
    GIntBig m_nMaxFeatureID = -1;
127
    bool m_bIsParquetLayer = false;
128
129
    std::vector<GeomColBBOX>
130
        m_geomColBBOX{};                     // same size as GetGeomFieldCount()
131
    std::vector<OGREnvelope3D> m_extents{};  // same size as GetGeomFieldCount()
132
    std::string m_osFIDColName{};
133
134
    OGRFeature *GetNextRawFeature();
135
    bool GetArrowStreamInternal(struct ArrowArrayStream *out_stream);
136
    GIntBig GetFeatureCountSelectCountStar();
137
    GIntBig GetFeatureCountArrow();
138
    GIntBig GetFeatureCountParquet();
139
140
    bool BuildLayerDefnInit();
141
    virtual void BuildLayerDefn();
142
    bool ReplaceStatement(const char *pszNewStatement);
143
    bool UpdateStatement();
144
    virtual std::string GetCurrentStatement() const;
145
146
    virtual bool RunDeferredCreation()
147
0
    {
148
0
        return true;
149
0
    }
150
151
    CPL_DISALLOW_COPY_ASSIGN(OGRADBCLayer)
152
153
  public:
154
    OGRADBCLayer(OGRADBCDataset *poDS, const char *pszName,
155
                 const std::string &osStatement, bool bInternalUse);
156
    OGRADBCLayer(OGRADBCDataset *poDS, const char *pszName,
157
                 std::unique_ptr<OGRArrowArrayStream> poStream,
158
                 ArrowSchema *schema, bool bInternalUse);
159
    ~OGRADBCLayer() override;
160
161
    bool GotError();
162
163
    using OGRLayer::GetLayerDefn;
164
    const OGRFeatureDefn *GetLayerDefn() const override;
165
166
    const char *GetName() const override
167
0
    {
168
0
        return GetDescription();
169
0
    }
170
171
    void ResetReading() override;
172
    DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRADBCLayer)
173
    int TestCapability(const char *) const override;
174
    GDALDataset *GetDataset() override;
175
    bool GetArrowStream(struct ArrowArrayStream *out_stream,
176
                        CSLConstList papszOptions = nullptr) override;
177
    GIntBig GetFeatureCount(int bForce) override;
178
179
    OGRErr SetAttributeFilter(const char *pszFilter) override;
180
    OGRErr ISetSpatialFilter(int iGeomField,
181
                             const OGRGeometry *poGeom) override;
182
183
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
184
                      bool bForce) override;
185
    OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
186
                        bool bForce) override;
187
188
    const char *GetFIDColumn() const override;
189
};
190
191
/************************************************************************/
192
/*                         OGRADBCBigQueryLayer                         */
193
/************************************************************************/
194
195
class OGRADBCBigQueryLayer final : public OGRADBCLayer
196
{
197
  private:
198
    friend class OGRADBCDataset;
199
200
    bool m_bDeferredCreation = false;
201
202
    void BuildLayerDefn() override;
203
    bool RunDeferredCreation() override;
204
    std::string GetCurrentStatement() const override;
205
    bool GetBigQueryDatasetAndTableId(std::string &osDatasetId,
206
                                      std::string &osTableId) const;
207
208
  public:
209
    OGRADBCBigQueryLayer(OGRADBCDataset *poDS, const char *pszName,
210
                         const std::string &osStatement, bool bInternalUse);
211
212
    int TestCapability(const char *) const override;
213
    GIntBig GetFeatureCount(int bForce) override;
214
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
215
                      bool bForce) override;
216
    OGRErr SetAttributeFilter(const char *pszFilter) override;
217
218
    OGRErr CreateField(const OGRFieldDefn *poField, int bApproxOK) override;
219
    OGRErr ICreateFeature(OGRFeature *poFeature) override;
220
    OGRErr ISetFeature(OGRFeature *poFeature) override;
221
    OGRErr DeleteFeature(GIntBig nFID) override;
222
223
    void SetDeferredCreation(const char *pszFIDColName,
224
                             const OGRGeomFieldDefn *poGeomFieldDefn);
225
};
226
227
/************************************************************************/
228
/*                            OGRADBCDataset                            */
229
/************************************************************************/
230
231
class OGRADBCDataset final : public GDALDataset
232
{
233
    friend class OGRADBCLayer;
234
235
    AdbcDriver m_driver{};
236
    AdbcDatabase m_database{};
237
    std::unique_ptr<AdbcConnection> m_connection{};
238
    std::vector<std::unique_ptr<OGRLayer>> m_apoLayers{};
239
    std::string m_osParquetFilename{};
240
    bool m_bIsDuckDBDataset = false;
241
    bool m_bIsDuckDBDriver = false;
242
    bool m_bSpatialLoaded = false;
243
    bool m_bIsBigQuery = false;
244
    std::string m_osBigQueryDatasetId{};
245
246
  public:
247
25
    OGRADBCDataset() = default;
248
    ~OGRADBCDataset() override;
249
250
    CPLErr FlushCache(bool bAtClosing) override;
251
252
    bool Open(const GDALOpenInfo *poOpenInfo);
253
254
    int GetLayerCount() const override
255
0
    {
256
0
        return static_cast<int>(m_apoLayers.size());
257
0
    }
258
259
    const OGRLayer *GetLayer(int idx) const override
260
0
    {
261
0
        return (idx >= 0 && idx < GetLayerCount()) ? m_apoLayers[idx].get()
262
0
                                                   : nullptr;
263
0
    }
264
265
    OGRLayer *GetLayerByName(const char *pszName) override;
266
267
    std::unique_ptr<OGRADBCLayer> CreateLayer(const char *pszStatement,
268
                                              const char *pszLayerName,
269
                                              bool bInternalUse);
270
271
    std::unique_ptr<OGRADBCLayer>
272
    CreateInternalLayer(const char *pszStatement) CPL_WARN_UNUSED_RESULT;
273
274
    OGRLayer *ICreateLayer(const char *pszName,
275
                           const OGRGeomFieldDefn *poGeomFieldDefn,
276
                           CSLConstList papszOptions) override;
277
    OGRErr DeleteLayer(int iLayer) override;
278
279
    OGRLayer *ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
280
                         const char *pszDialect) override;
281
282
    int TestCapability(const char *pszCap) const override;
283
};
284
285
/************************************************************************/
286
/*                             OGRADBCError                             */
287
/************************************************************************/
288
289
struct OGRADBCError
290
{
291
    AdbcError error{ADBC_ERROR_INIT};
292
293
50
    inline OGRADBCError() = default;
294
295
    inline ~OGRADBCError()
296
50
    {
297
50
        clear();
298
50
    }
299
300
    inline void clear()
301
75
    {
302
75
        if (error.release)
303
0
            error.release(&error);
304
75
        memset(&error, 0, sizeof(error));
305
75
    }
306
307
    inline const char *message() const
308
0
    {
309
0
        return error.message ? error.message : "";
310
0
    }
311
312
    inline operator AdbcError *()
313
0
    {
314
0
        return &error;
315
0
    }
316
317
    CPL_DISALLOW_COPY_ASSIGN(OGRADBCError)
318
};
319
320
#endif  // OGR_ADBC_INCLUDED