Coverage Report

Created: 2026-04-01 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogr_schema_override.h
Line
Count
Source
1
/******************************************************************************
2
 * Project:  OGR_SCHEMA open options handling
3
 * Purpose:  Class for representing a layer schema override.
4
 * Author:   Alessandro Pasotti, elpaso@itopen.it
5
 *
6
 ******************************************************************************
7
 * Copyright (c) 2024, Alessandro Pasotti <elpaso at itopen dot it>
8
 *
9
 * SPDX-License-Identifier: MIT
10
 ****************************************************************************/
11
12
#ifndef OGR_SCHEMA_OVERRIDE_H_INCLUDED
13
#define OGR_SCHEMA_OVERRIDE_H_INCLUDED
14
15
//! @cond Doxygen_Suppress
16
17
#include <functional>
18
#include <string>
19
#include <map>
20
#include <optional>
21
#include <ogr_api.h>
22
#include <ogr_feature.h>
23
#include <cpl_vsi.h>
24
#include <cpl_json.h>
25
26
/** Class that holds the schema override options for a single field */
27
class CPL_DLL OGRFieldDefnOverride
28
{
29
  public:
30
0
    OGRFieldDefnOverride() = default;
31
32
    void SetFieldName(const std::string &osName)
33
0
    {
34
0
        m_osName = osName;
35
0
    }
36
37
    void SetSrcFieldType(OGRFieldType eType)
38
0
    {
39
0
        m_eSrcType = eType;
40
0
    }
41
42
    void SetSrcFieldSubType(OGRFieldSubType eSubType)
43
0
    {
44
0
        m_eSrcSubType = eSubType;
45
0
    }
46
47
    void SetFieldType(OGRFieldType eType)
48
0
    {
49
0
        m_eType = eType;
50
0
    }
51
52
    void SetFieldSubType(OGRFieldSubType eSubType)
53
0
    {
54
0
        m_eSubType = eSubType;
55
0
    }
56
57
    void SetFieldWidth(int nWidth)
58
0
    {
59
0
        m_nWidth = nWidth;
60
0
    }
61
62
    void SetFieldPrecision(int nPrecision)
63
0
    {
64
0
        m_nPrecision = nPrecision;
65
0
    }
66
67
    void SetNullable(bool bNullable)
68
0
    {
69
0
        m_bNullable = bNullable;
70
0
    }
71
72
    void SetUnique(bool bUnique)
73
0
    {
74
0
        m_bUnique = bUnique;
75
0
    }
76
77
    void SetComment(const std::string &osComment)
78
0
    {
79
0
        m_osComment = osComment;
80
0
    }
81
82
    void SetAlias(const std::string &osAlias)
83
0
    {
84
0
        m_osAlias = osAlias;
85
0
    }
86
87
    void SetTimezone(const std::string &osTimezone)
88
0
    {
89
0
        m_osTimezone = osTimezone;
90
0
    }
91
92
    void SetDomainName(const std::string &osDomainName)
93
0
    {
94
0
        m_osDomainName = osDomainName;
95
0
    }
96
97
    void SetDefaultValue(const std::string &osDefaultValue)
98
0
    {
99
0
        m_osDefaultValue = osDefaultValue;
100
0
    }
101
102
    std::optional<std::string> GetFieldName() const
103
0
    {
104
0
        return m_osName;
105
0
    }
106
107
    std::optional<OGRFieldType> GetSrcFieldType() const
108
0
    {
109
0
        return m_eSrcType;
110
0
    }
111
112
    std::optional<OGRFieldSubType> GetSrcFieldSubType() const
113
0
    {
114
0
        return m_eSrcSubType;
115
0
    }
116
117
    std::optional<OGRFieldType> GetFieldType() const
118
0
    {
119
0
        return m_eType;
120
0
    }
121
122
    std::optional<OGRFieldSubType> GetFieldSubType() const
123
0
    {
124
0
        return m_eSubType;
125
0
    }
126
127
    std::optional<int> GetFieldWidth() const
128
0
    {
129
0
        return m_nWidth;
130
0
    }
131
132
    std::optional<int> GetFieldPrecision() const
133
0
    {
134
0
        return m_nPrecision;
135
0
    }
136
137
    std::optional<int> GetNullable() const
138
0
    {
139
0
        return m_bNullable;
140
0
    }
141
142
    std::optional<int> GetUnique() const
143
0
    {
144
0
        return m_bUnique;
145
0
    }
146
147
    std::optional<std::string> GetComment() const
148
0
    {
149
0
        return m_osComment;
150
0
    }
151
152
    std::optional<std::string> GetAlias() const
153
0
    {
154
0
        return m_osAlias;
155
0
    }
156
157
    std::optional<std::string> GetTimezone() const
158
0
    {
159
0
        return m_osTimezone;
160
0
    }
161
162
    std::optional<std::string> GetDomainName() const
163
0
    {
164
0
        return m_osDomainName;
165
0
    }
166
167
    // Considered valid if it carries any change information, otherwise it's considered a no-op
168
    bool IsValid() const;
169
170
    /**
171
     *  Build an OGRFieldDefn based on the override information.
172
     *  \a osDefaultName is used as field name if the override doesn't specify one.
173
     */
174
    OGRFieldDefn ToFieldDefn(const std::string &osDefaultName) const;
175
176
  private:
177
    std::optional<std::string> m_osName{};
178
    std::optional<OGRFieldType> m_eSrcType{};
179
    std::optional<OGRFieldSubType> m_eSrcSubType{};
180
    std::optional<OGRFieldType> m_eType{};
181
    std::optional<OGRFieldSubType> m_eSubType{};
182
    std::optional<int> m_nWidth{};
183
    std::optional<int> m_nPrecision{};
184
    std::optional<bool> m_bUnique{};
185
    std::optional<bool> m_bNullable{};
186
    std::optional<std::string> m_osComment{};
187
    std::optional<std::string> m_osAlias{};
188
    std::optional<std::string> m_osTimezone{};
189
    std::optional<std::string> m_osDomainName{};
190
    std::optional<std::string> m_osDefaultValue{};
191
};
192
193
/**
194
 *  Class that holds the schema override options for a single geometry field
195
 */
196
class CPL_DLL OGRGeomFieldDefnOverride
197
{
198
  public:
199
0
    OGRGeomFieldDefnOverride() = default;
200
201
    void SetFieldName(const std::string &osName)
202
0
    {
203
0
        m_osName = osName;
204
0
    }
205
206
    void SetGeometryType(OGRwkbGeometryType eType)
207
0
    {
208
0
        m_eType = eType;
209
0
    }
210
211
    void SetSRS(const OGRSpatialReference &oSRS)
212
0
    {
213
0
        m_oSRS = oSRS;
214
0
    }
215
216
    void SetNullable(bool bNullable)
217
0
    {
218
0
        m_bNullable = bNullable;
219
0
    }
220
221
    std::optional<std::string> GetFieldName() const
222
0
    {
223
0
        return m_osName;
224
0
    }
225
226
    std::optional<OGRwkbGeometryType> GetGeometryType() const
227
0
    {
228
0
        return m_eType;
229
0
    }
230
231
    std::optional<OGRSpatialReference> GetSRS() const
232
0
    {
233
0
        return m_oSRS;
234
0
    }
235
236
    std::optional<bool> GetNullable() const
237
0
    {
238
0
        return m_bNullable;
239
0
    }
240
241
    /**
242
     *  Build an OGRGeometryFieldDefn based on the override information.
243
     *  \a osDefaultName is used as field name if the override doesn't specify one.
244
     *  If the override doesn't specify a type, wkbUnknown is used as default type.
245
     */
246
    OGRGeomFieldDefn
247
    ToGeometryFieldDefn(const std::string &osDefaultName) const;
248
249
  private:
250
    std::optional<bool> m_bNullable{};
251
    std::optional<std::string> m_osName{};
252
    std::optional<OGRwkbGeometryType> m_eType{};
253
    std::optional<OGRSpatialReference> m_oSRS{};
254
};
255
256
/** Class that holds the schema override options for a single layer */
257
class CPL_DLL OGRLayerSchemaOverride
258
{
259
  public:
260
0
    OGRLayerSchemaOverride() = default;
261
262
    void SetLayerName(const std::string &osLayerName);
263
264
    void AddNamedFieldOverride(const std::string &osFieldName,
265
                               const OGRFieldDefnOverride &oFieldOverride);
266
267
    void AddUnnamedFieldOverride(const OGRFieldDefnOverride &oFieldOverride);
268
269
    const std::string &GetLayerName() const;
270
271
    const std::map<std::string, OGRFieldDefnOverride> &
272
    GetNamedFieldOverrides() const;
273
274
    const std::vector<OGRFieldDefnOverride> &GetUnnamedFieldOverrides() const;
275
276
    void AddGeometryFieldOverride(
277
        const OGRGeomFieldDefnOverride &oGeomFieldOverride);
278
279
    const std::vector<OGRGeomFieldDefnOverride> &
280
    GetGeometryFieldOverrides() const;
281
282
    std::vector<OGRFieldDefn> GetFieldDefinitions() const;
283
284
    std::vector<OGRGeomFieldDefn> GetGeomFieldDefinitions() const;
285
286
    bool IsFullOverride() const;
287
288
    void SetFullOverride(bool bIsFullOverride);
289
290
    bool IsValid() const;
291
292
    bool empty() const;
293
294
  private:
295
    std::string m_osLayerName{};
296
    std::map<std::string, OGRFieldDefnOverride> m_oNamedFieldOverrides{};
297
    std::vector<OGRFieldDefnOverride> m_aoUnnamedFieldOverrides{};
298
    std::vector<OGRGeomFieldDefnOverride> m_aoGeomFieldOverrides{};
299
    bool m_bIsFullOverride = false;
300
};
301
302
class GDALDataset;
303
304
/** Class that holds the schema override options for a datasource */
305
class CPL_DLL OGRSchemaOverride
306
{
307
  public:
308
0
    OGRSchemaOverride() = default;
309
310
    void AddLayerOverride(const OGRLayerSchemaOverride &oLayerOverride);
311
312
    /**
313
     * Load an override schema from JSON string that follows OGR_SCHEMA specification.
314
     * @param osJSON JSON string
315
     * @param bAllowGeometryFields Whether to allow a geometry fields in the JSON (normally not overridable but allowed if the schema is applied to a dataset that doesn't have any geometry field, so that it can be used to create a geometry field in that case)
316
     * @return TRUE if the JSON was successfully parsed and the schema override is valid, FALSE otherwise
317
     */
318
    bool LoadFromJSON(const std::string &osJSON,
319
                      bool bAllowGeometryFields = false);
320
321
    const std::vector<OGRLayerSchemaOverride> &GetLayerOverrides() const;
322
323
    bool IsValid() const;
324
325
    /**
326
     *  Default implementation to apply the overrides to a dataset
327
     *  \note geometry fields are ignored (not overridable)
328
     */
329
    bool DefaultApply(
330
        GDALDataset *poDS, const char *pszDebugKey,
331
        std::function<void(OGRLayer *, int)> callbackWhenRemovingField =
332
0
            [](OGRLayer *, int) {}) const;
333
334
    const OGRLayerSchemaOverride &
335
    GetLayerOverride(const std::string &osLayerName) const;
336
337
  private:
338
    std::vector<OGRLayerSchemaOverride> m_aoLayerOverrides{};
339
};
340
341
//! @endcond
342
343
#endif /* ndef OGR_FEATURE_H_INCLUDED */