Coverage Report

Created: 2026-04-10 07:04

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 SetFIDColumnName(const std::string &osFIDColumnName);
265
266
    void AddNamedFieldOverride(const std::string &osFieldName,
267
                               const OGRFieldDefnOverride &oFieldOverride);
268
269
    void AddUnnamedFieldOverride(const OGRFieldDefnOverride &oFieldOverride);
270
271
    const std::string &GetLayerName() const;
272
273
    const std::string &GetFIDColumnName() const;
274
275
    const std::map<std::string, OGRFieldDefnOverride> &
276
    GetNamedFieldOverrides() const;
277
278
    const std::vector<OGRFieldDefnOverride> &GetUnnamedFieldOverrides() const;
279
280
    void AddGeometryFieldOverride(
281
        const OGRGeomFieldDefnOverride &oGeomFieldOverride);
282
283
    const std::vector<OGRGeomFieldDefnOverride> &
284
    GetGeometryFieldOverrides() const;
285
286
    std::vector<OGRFieldDefn> GetFieldDefinitions() const;
287
288
    std::vector<OGRGeomFieldDefn> GetGeomFieldDefinitions() const;
289
290
    bool IsFullOverride() const;
291
292
    void SetFullOverride(bool bIsFullOverride);
293
294
    bool IsValid() const;
295
296
    bool empty() const;
297
298
  private:
299
    std::string m_osLayerName{};
300
    std::string m_osFIDColumnName{};
301
    std::map<std::string, OGRFieldDefnOverride> m_oNamedFieldOverrides{};
302
    std::vector<OGRFieldDefnOverride> m_aoUnnamedFieldOverrides{};
303
    std::vector<OGRGeomFieldDefnOverride> m_aoGeomFieldOverrides{};
304
    bool m_bIsFullOverride = false;
305
};
306
307
class GDALDataset;
308
309
/** Class that holds the schema override options for a datasource */
310
class CPL_DLL OGRSchemaOverride
311
{
312
  public:
313
0
    OGRSchemaOverride() = default;
314
315
    void AddLayerOverride(const OGRLayerSchemaOverride &oLayerOverride);
316
317
    /**
318
     * Load an override schema from JSON string that follows OGR_SCHEMA specification.
319
     * @param osJSON JSON string
320
     * @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)
321
     * @return TRUE if the JSON was successfully parsed and the schema override is valid, FALSE otherwise
322
     */
323
    bool LoadFromJSON(const std::string &osJSON,
324
                      bool bAllowGeometryFields = false);
325
326
    const std::vector<OGRLayerSchemaOverride> &GetLayerOverrides() const;
327
328
    bool IsValid() const;
329
330
    /**
331
     *  Default implementation to apply the overrides to a dataset
332
     *  \note geometry fields are ignored (not overridable)
333
     */
334
    bool DefaultApply(
335
        GDALDataset *poDS, const char *pszDebugKey,
336
        std::function<void(OGRLayer *, int)> callbackWhenRemovingField =
337
0
            [](OGRLayer *, int) {}) const;
338
339
    const OGRLayerSchemaOverride &
340
    GetLayerOverride(const std::string &osLayerName) const;
341
342
  private:
343
    std::vector<OGRLayerSchemaOverride> m_aoLayerOverrides{};
344
};
345
346
//! @endcond
347
348
#endif /* ndef OGR_FEATURE_H_INCLUDED */