Coverage Report

Created: 2025-08-11 09:23

/src/gdal/ogr/ogrsf_frmts/adbc/ogr_adbc.h
Line
Count
Source (jump to first uncovered line)
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
    OGRFeatureDefn *GetLayerDefn() override
45
0
    {
46
0
        return m_poLayerDefn;
47
0
    }
48
49
    void ResetReading() override
50
0
    {
51
0
    }
52
53
    OGRFeature *GetNextFeature() override
54
0
    {
55
0
        return nullptr;
56
0
    }
57
58
    int TestCapability(const char *pszCap) override
59
0
    {
60
0
        return EQUAL(pszCap, OLCCreateField) ||
61
0
               EQUAL(pszCap, OLCSequentialWrite);
62
0
    }
63
64
    OGRErr CreateField(const OGRFieldDefn *poFieldDefn, int) override
65
0
    {
66
0
        m_poLayerDefn->AddFieldDefn(poFieldDefn);
67
0
        return OGRERR_NONE;
68
0
    }
69
70
    OGRErr ICreateFeature(OGRFeature *poFeature) override
71
0
    {
72
0
        m_apoFeatures.emplace_back(
73
0
            std::unique_ptr<OGRFeature>(poFeature->Clone()));
74
0
        return OGRERR_NONE;
75
0
    }
76
};
77
78
/************************************************************************/
79
/*                            OGRADBCLayer                              */
80
/************************************************************************/
81
82
class OGRADBCDataset;
83
84
class OGRADBCLayer final : public OGRLayer,
85
                           public OGRGetNextFeatureThroughRaw<OGRADBCLayer>
86
{
87
  public:
88
    //! Describe the bbox column of a geometry column
89
    struct GeomColBBOX
90
    {
91
        std::string osXMin{};  // empty if no bbox column
92
        std::string osYMin{};
93
        std::string osXMax{};
94
        std::string osYMax{};
95
    };
96
97
  private:
98
    friend class OGRADBCDataset;
99
100
    OGRADBCDataset *m_poDS = nullptr;
101
    const std::string m_osBaseStatement{};    // as provided by user
102
    std::string m_osModifiedBaseStatement{};  // above tuned to use ST_AsWKB()
103
    std::string m_osModifiedSelect{};         // SELECT part of above
104
    std::string m_osAttributeFilter{};
105
    std::unique_ptr<AdbcStatement> m_statement{};
106
    std::unique_ptr<OGRArrowArrayToOGRFeatureAdapterLayer> m_poAdapterLayer{};
107
    std::unique_ptr<OGRArrowArrayStream> m_stream{};
108
109
    struct ArrowSchema m_schema
110
    {
111
    };
112
113
    bool m_bEOF = false;
114
    size_t m_nIdx = 0;
115
    GIntBig m_nFeatureID = 0;
116
    bool m_bIsParquetLayer = false;
117
118
    std::vector<GeomColBBOX>
119
        m_geomColBBOX{};                     // same size as GetGeomFieldCount()
120
    std::vector<OGREnvelope3D> m_extents{};  // same size as GetGeomFieldCount()
121
122
    OGRFeature *GetNextRawFeature();
123
    bool GetArrowStreamInternal(struct ArrowArrayStream *out_stream);
124
    GIntBig GetFeatureCountParquet();
125
126
    void BuildLayerDefn(bool bInternalUse);
127
    bool ReplaceStatement(const char *pszNewStatement);
128
    bool UpdateStatement();
129
    std::string GetCurrentStatement() const;
130
131
    CPL_DISALLOW_COPY_ASSIGN(OGRADBCLayer)
132
133
  public:
134
    OGRADBCLayer(OGRADBCDataset *poDS, const char *pszName,
135
                 const char *pszStatement,
136
                 std::unique_ptr<AdbcStatement> poStatement,
137
                 std::unique_ptr<OGRArrowArrayStream> poStream,
138
                 ArrowSchema *schema, bool bInternalUse);
139
    ~OGRADBCLayer() override;
140
141
    OGRFeatureDefn *GetLayerDefn() override
142
0
    {
143
0
        return m_poAdapterLayer->GetLayerDefn();
144
0
    }
145
146
    void ResetReading() override;
147
    DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRADBCLayer)
148
    int TestCapability(const char *) override;
149
    GDALDataset *GetDataset() override;
150
    bool GetArrowStream(struct ArrowArrayStream *out_stream,
151
                        CSLConstList papszOptions = nullptr) override;
152
    GIntBig GetFeatureCount(int bForce) override;
153
154
    OGRErr SetAttributeFilter(const char *pszFilter) override;
155
    OGRErr ISetSpatialFilter(int iGeomField,
156
                             const OGRGeometry *poGeom) override;
157
158
    OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
159
                      bool bForce) override;
160
    OGRErr IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent,
161
                        bool bForce) override;
162
};
163
164
/************************************************************************/
165
/*                            OGRADBCDataset                            */
166
/************************************************************************/
167
168
class OGRADBCDataset final : public GDALDataset
169
{
170
    friend class OGRADBCLayer;
171
172
    AdbcDriver m_driver{};
173
    AdbcDatabase m_database{};
174
    std::unique_ptr<AdbcConnection> m_connection{};
175
    std::vector<std::unique_ptr<OGRLayer>> m_apoLayers{};
176
    std::string m_osParquetFilename{};
177
    bool m_bIsDuckDBDataset = false;
178
    bool m_bIsDuckDBDriver = false;
179
    bool m_bSpatialLoaded = false;
180
181
  public:
182
36
    OGRADBCDataset() = default;
183
    ~OGRADBCDataset() override;
184
185
    bool Open(const GDALOpenInfo *poOpenInfo);
186
187
    int GetLayerCount() override
188
0
    {
189
0
        return static_cast<int>(m_apoLayers.size());
190
0
    }
191
192
    OGRLayer *GetLayer(int idx) override
193
0
    {
194
0
        return (idx >= 0 && idx < GetLayerCount()) ? m_apoLayers[idx].get()
195
0
                                                   : nullptr;
196
0
    }
197
198
    OGRLayer *GetLayerByName(const char *pszName) override;
199
200
    std::unique_ptr<OGRADBCLayer> CreateLayer(const char *pszStatement,
201
                                              const char *pszLayerName,
202
                                              bool bInternalUse);
203
204
    std::unique_ptr<OGRADBCLayer> CreateInternalLayer(const char *pszStatement)
205
0
    {
206
0
        return CreateLayer(pszStatement, "temp", true);
207
0
    }
208
209
    OGRLayer *ExecuteSQL(const char *pszStatement, OGRGeometry *poSpatialFilter,
210
                         const char *pszDialect) override;
211
};
212
213
/************************************************************************/
214
/*                            OGRADBCError                              */
215
/************************************************************************/
216
217
struct OGRADBCError
218
{
219
    AdbcError error{ADBC_ERROR_INIT};
220
221
72
    inline OGRADBCError() = default;
222
223
    inline ~OGRADBCError()
224
72
    {
225
72
        clear();
226
72
    }
227
228
    inline void clear()
229
108
    {
230
108
        if (error.release)
231
0
            error.release(&error);
232
108
        memset(&error, 0, sizeof(error));
233
108
    }
234
235
    inline const char *message() const
236
0
    {
237
0
        return error.message ? error.message : "";
238
0
    }
239
240
    inline operator AdbcError *()
241
0
    {
242
0
        return &error;
243
0
    }
244
245
    CPL_DISALLOW_COPY_ASSIGN(OGRADBCError)
246
};
247
248
#endif  // OGR_ADBC_INCLUDED