• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-engine / geoengine / 6038596548

31 Aug 2023 02:19PM UTC coverage: 90.097% (+0.06%) from 90.041%
6038596548

push

github

web-flow
Merge pull request #866 from geo-engine/provider-def-mapping

refactor provider defs to pro/non-pro

991 of 991 new or added lines in 21 files covered. (100.0%)

106888 of 118637 relevant lines covered (90.1%)

61031.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.06
/services/src/api/model/db_types.rs
1
use super::{
2
    datatypes::{
3
        BoundingBox2D, Breakpoint, ClassificationMeasurement, Colorizer, ContinuousMeasurement,
4
        Coordinate2D, DateTimeParseFormat, DefaultColors, FeatureDataType, LinearGradient,
5
        LogarithmicGradient, Measurement, MultiLineString, MultiPoint, MultiPolygon, NoGeometry,
6
        OverUnderColors, Palette, RgbaColor, SpatialReferenceOption, TimeInstance, TimeInterval,
7
        TimeStep, VectorDataType,
8
    },
9
    operators::{
10
        CsvHeader, FileNotFoundHandling, FormatSpecifics, GdalConfigOption,
11
        GdalDatasetGeoTransform, GdalDatasetParameters, GdalMetaDataList, GdalMetaDataRegular,
12
        GdalMetaDataStatic, GdalMetadataMapping, GdalMetadataNetCdfCf, GdalSourceTimePlaceholder,
13
        MockDatasetDataSourceLoadingInfo, MockMetaData, OgrMetaData, OgrSourceColumnSpec,
14
        OgrSourceDataset, OgrSourceDatasetTimeType, OgrSourceDurationSpec, OgrSourceErrorSpec,
15
        OgrSourceTimeFormat, PlotResultDescriptor, RasterResultDescriptor, TypedGeometry,
16
        TypedResultDescriptor, UnixTimeStampType, VectorColumnInfo, VectorResultDescriptor,
17
    },
18
};
19
use crate::{
20
    datasets::{
21
        external::{
22
            aruna::ArunaDataProviderDefinition,
23
            gbif::GbifDataProviderDefinition,
24
            gfbio_abcd::GfbioAbcdDataProviderDefinition,
25
            gfbio_collections::GfbioCollectionsDataProviderDefinition,
26
            netcdfcf::{EbvPortalDataProviderDefinition, NetCdfCfDataProviderDefinition},
27
            pangaea::PangaeaDataProviderDefinition,
28
        },
29
        storage::MetaDataDefinition,
30
    },
31
    error::Error,
32
    layers::external::TypedDataProviderDefinition,
33
    projects::{
34
        ColorParam, DerivedColor, DerivedNumber, LineSymbology, NumberParam, PointSymbology,
35
        PolygonSymbology, RasterSymbology, Symbology,
36
    },
37
    util::postgres::DatabaseConnectionConfig,
38
};
39
use fallible_iterator::FallibleIterator;
40
use geoengine_datatypes::primitives::CacheTtlSeconds;
41
use ordered_float::NotNan;
42
use postgres_types::{FromSql, ToSql};
43
use std::{collections::HashMap, marker::PhantomData};
44

45
#[derive(Debug, ToSql, FromSql)]
9,928✔
46
#[postgres(name = "DefaultColors")]
47
pub struct DefaultColorsDbType {
48
    pub default_color: Option<RgbaColor>,
49
    pub over_color: Option<RgbaColor>,
50
    pub under_color: Option<RgbaColor>,
51
}
52

53
impl From<&DefaultColors> for DefaultColorsDbType {
54
    fn from(value: &DefaultColors) -> Self {
15✔
55
        match value {
15✔
56
            DefaultColors::DefaultColor { default_color } => Self {
1✔
57
                default_color: Some(*default_color),
1✔
58
                over_color: None,
1✔
59
                under_color: None,
1✔
60
            },
1✔
61
            DefaultColors::OverUnder(over_under) => Self {
14✔
62
                default_color: None,
14✔
63
                over_color: Some(over_under.over_color),
14✔
64
                under_color: Some(over_under.under_color),
14✔
65
            },
14✔
66
        }
67
    }
15✔
68
}
69

70
impl TryFrom<DefaultColorsDbType> for DefaultColors {
71
    type Error = Error;
72

73
    fn try_from(value: DefaultColorsDbType) -> Result<Self, Self::Error> {
74
        match (value.default_color, value.over_color, value.under_color) {
13✔
75
            (Some(default_color), None, None) => Ok(Self::DefaultColor { default_color }),
1✔
76
            (None, Some(over_color), Some(under_color)) => Ok(Self::OverUnder(OverUnderColors {
12✔
77
                over_color,
12✔
78
                under_color,
12✔
79
            })),
12✔
80
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
81
        }
82
    }
13✔
83
}
84

85
#[derive(Debug, ToSql, FromSql)]
14,868✔
86
#[postgres(name = "Colorizer")]
87
pub struct ColorizerDbType {
88
    r#type: ColorizerTypeDbType,
89
    breakpoints: Option<Vec<Breakpoint>>,
90
    no_data_color: Option<RgbaColor>,
91
    color_fields: Option<DefaultColorsDbType>,
92
    default_color: Option<RgbaColor>,
93
}
94

95
#[derive(Debug, PartialEq, ToSql, FromSql)]
12,410✔
96
// TODO: use #[postgres(rename_all = "camelCase")]
97
#[postgres(name = "ColorizerType")]
98
pub enum ColorizerTypeDbType {
99
    LinearGradient,
100
    LogarithmicGradient,
101
    Palette,
102
    Rgba,
103
}
104

105
impl From<&Colorizer> for ColorizerDbType {
106
    fn from(value: &Colorizer) -> Self {
25✔
107
        match value {
25✔
108
            Colorizer::LinearGradient(gradient) => ColorizerDbType {
12✔
109
                r#type: ColorizerTypeDbType::LinearGradient,
12✔
110
                breakpoints: Some(gradient.breakpoints.clone()),
12✔
111
                no_data_color: Some(gradient.no_data_color),
12✔
112
                color_fields: Some((&gradient.color_fields).into()),
12✔
113
                default_color: None,
12✔
114
            },
12✔
115
            Colorizer::LogarithmicGradient(gradient) => ColorizerDbType {
1✔
116
                r#type: ColorizerTypeDbType::LogarithmicGradient,
1✔
117
                breakpoints: Some(gradient.breakpoints.clone()),
1✔
118
                no_data_color: Some(gradient.no_data_color),
1✔
119
                color_fields: Some((&gradient.color_fields).into()),
1✔
120
                default_color: None,
1✔
121
            },
1✔
122
            Colorizer::Palette {
123
                colors,
3✔
124
                no_data_color,
3✔
125
                default_color,
3✔
126
            } => ColorizerDbType {
3✔
127
                r#type: ColorizerTypeDbType::Palette,
3✔
128
                breakpoints: Some(
3✔
129
                    colors
3✔
130
                        .0
3✔
131
                        .iter()
3✔
132
                        .map(|(k, v)| Breakpoint {
276✔
133
                            value: (*k).into(),
276✔
134
                            color: *v,
276✔
135
                        })
276✔
136
                        .collect(),
3✔
137
                ),
3✔
138
                no_data_color: Some(*no_data_color),
3✔
139
                color_fields: None,
3✔
140
                default_color: Some(*default_color),
3✔
141
            },
3✔
142
            Colorizer::Rgba => ColorizerDbType {
9✔
143
                r#type: ColorizerTypeDbType::Rgba,
9✔
144
                breakpoints: None,
9✔
145
                no_data_color: None,
9✔
146
                color_fields: None,
9✔
147
                default_color: None,
9✔
148
            },
9✔
149
        }
150
    }
25✔
151
}
152

153
impl TryFrom<ColorizerDbType> for Colorizer {
154
    type Error = Error;
155

156
    fn try_from(value: ColorizerDbType) -> Result<Self, Self::Error> {
157
        match value {
10✔
158
            ColorizerDbType {
159
                r#type: ColorizerTypeDbType::LinearGradient,
160
                breakpoints: Some(breakpoints),
10✔
161
                no_data_color: Some(no_data_color),
10✔
162
                color_fields: Some(color_fields),
10✔
163
                default_color: None,
10✔
164
            } => Ok(Self::LinearGradient(LinearGradient {
10✔
165
                breakpoints,
10✔
166
                no_data_color,
10✔
167
                color_fields: color_fields.try_into()?,
10✔
168
            })),
169
            ColorizerDbType {
170
                r#type: ColorizerTypeDbType::LogarithmicGradient,
171
                breakpoints: Some(breakpoints),
1✔
172
                no_data_color: Some(no_data_color),
1✔
173
                color_fields: Some(color_fields),
1✔
174
                default_color: None,
1✔
175
            } => Ok(Self::LogarithmicGradient(LogarithmicGradient {
1✔
176
                breakpoints,
1✔
177
                no_data_color,
1✔
178
                color_fields: color_fields.try_into()?,
1✔
179
            })),
180
            ColorizerDbType {
181
                r#type: ColorizerTypeDbType::Palette,
182
                breakpoints: Some(breakpoints),
1✔
183
                no_data_color: Some(no_data_color),
1✔
184
                color_fields: None,
1✔
185
                default_color: Some(default_color),
1✔
186
            } => Ok(Self::Palette {
1✔
187
                colors: Palette(
1✔
188
                    breakpoints
1✔
189
                        .into_iter()
1✔
190
                        .map(|b| (NotNan::<f64>::from(b.value), b.color))
3✔
191
                        .collect(),
1✔
192
                ),
1✔
193
                no_data_color,
1✔
194
                default_color,
1✔
195
            }),
1✔
196
            ColorizerDbType {
197
                r#type: ColorizerTypeDbType::Rgba,
198
                breakpoints: None,
199
                no_data_color: None,
200
                color_fields: None,
201
                default_color: None,
202
            } => Ok(Self::Rgba),
13✔
203
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
204
        }
205
    }
25✔
206
}
207

208
#[derive(Debug, ToSql, FromSql)]
9,060✔
209
#[postgres(name = "ColorParam")]
210
pub struct ColorParamDbType {
211
    color: Option<RgbaColor>,
212
    attribute: Option<String>,
213
    colorizer: Option<Colorizer>,
214
}
215

216
impl From<&ColorParam> for ColorParamDbType {
217
    fn from(value: &ColorParam) -> Self {
36✔
218
        match value {
36✔
219
            ColorParam::Static { color } => Self {
35✔
220
                color: Some((*color).into()),
35✔
221
                attribute: None,
35✔
222
                colorizer: None,
35✔
223
            },
35✔
224
            ColorParam::Derived(DerivedColor {
225
                attribute,
1✔
226
                colorizer,
1✔
227
            }) => Self {
1✔
228
                color: None,
1✔
229
                attribute: Some(attribute.clone()),
1✔
230
                colorizer: Some(colorizer.clone()),
1✔
231
            },
1✔
232
        }
233
    }
36✔
234
}
235

236
impl TryFrom<ColorParamDbType> for ColorParam {
237
    type Error = Error;
238

239
    fn try_from(value: ColorParamDbType) -> Result<Self, Self::Error> {
240
        match value {
1✔
241
            ColorParamDbType {
242
                color: Some(color),
29✔
243
                attribute: None,
29✔
244
                colorizer: None,
29✔
245
            } => Ok(Self::Static {
29✔
246
                color: color.into(),
29✔
247
            }),
29✔
248
            ColorParamDbType {
249
                color: None,
250
                attribute: Some(attribute),
1✔
251
                colorizer: Some(colorizer),
1✔
252
            } => Ok(Self::Derived(DerivedColor {
1✔
253
                attribute,
1✔
254
                colorizer,
1✔
255
            })),
1✔
256
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
257
        }
258
    }
30✔
259
}
260

261
#[derive(Debug, ToSql, FromSql)]
7,215✔
262
#[postgres(name = "NumberParam")]
263
pub struct NumberParamDbType {
264
    value: Option<i64>,
265
    attribute: Option<String>,
266
    factor: Option<f64>,
267
    default_value: Option<f64>,
268
}
269

270
impl From<&NumberParam> for NumberParamDbType {
271
    fn from(value: &NumberParam) -> Self {
31✔
272
        match value {
31✔
273
            NumberParam::Static { value } => Self {
30✔
274
                value: Some(*value as i64),
30✔
275
                attribute: None,
30✔
276
                factor: None,
30✔
277
                default_value: None,
30✔
278
            },
30✔
279
            NumberParam::Derived(DerivedNumber {
280
                attribute,
1✔
281
                factor,
1✔
282
                default_value,
1✔
283
            }) => Self {
1✔
284
                value: None,
1✔
285
                attribute: Some(attribute.clone()),
1✔
286
                factor: Some(*factor),
1✔
287
                default_value: Some(*default_value),
1✔
288
            },
1✔
289
        }
290
    }
31✔
291
}
292

293
impl TryFrom<NumberParamDbType> for NumberParam {
294
    type Error = Error;
295

296
    fn try_from(value: NumberParamDbType) -> Result<Self, Self::Error> {
297
        match value {
1✔
298
            NumberParamDbType {
299
                value: Some(value),
24✔
300
                attribute: None,
24✔
301
                factor: None,
24✔
302
                default_value: None,
24✔
303
            } => Ok(Self::Static {
24✔
304
                value: value as usize,
24✔
305
            }),
24✔
306
            NumberParamDbType {
307
                value: None,
308
                attribute: Some(attribute),
1✔
309
                factor: Some(factor),
1✔
310
                default_value: Some(default_value),
1✔
311
            } => Ok(Self::Derived(DerivedNumber {
1✔
312
                attribute,
1✔
313
                factor,
1✔
314
                default_value,
1✔
315
            })),
1✔
316
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
317
        }
318
    }
25✔
319
}
320

321
#[derive(Debug, ToSql, FromSql)]
1,025✔
322
#[postgres(name = "Symbology")]
323
pub struct SymbologyDbType {
324
    raster: Option<RasterSymbology>,
325
    point: Option<PointSymbology>,
326
    line: Option<LineSymbology>,
327
    polygon: Option<PolygonSymbology>,
328
}
329

330
impl From<&Symbology> for SymbologyDbType {
331
    fn from(symbology: &Symbology) -> Self {
33✔
332
        match symbology {
33✔
333
            Symbology::Raster(raster) => SymbologyDbType {
20✔
334
                raster: Some(raster.clone()),
20✔
335
                point: None,
20✔
336
                line: None,
20✔
337
                polygon: None,
20✔
338
            },
20✔
339
            Symbology::Point(point) => SymbologyDbType {
11✔
340
                raster: None,
11✔
341
                point: Some(point.clone()),
11✔
342
                line: None,
11✔
343
                polygon: None,
11✔
344
            },
11✔
345
            Symbology::Line(line) => SymbologyDbType {
1✔
346
                raster: None,
1✔
347
                point: None,
1✔
348
                line: Some(line.clone()),
1✔
349
                polygon: None,
1✔
350
            },
1✔
351
            Symbology::Polygon(polygon) => SymbologyDbType {
1✔
352
                raster: None,
1✔
353
                point: None,
1✔
354
                line: None,
1✔
355
                polygon: Some(polygon.clone()),
1✔
356
            },
1✔
357
        }
358
    }
33✔
359
}
360

361
impl TryFrom<SymbologyDbType> for Symbology {
362
    type Error = Error;
363

364
    fn try_from(symbology: SymbologyDbType) -> Result<Self, Self::Error> {
365
        match symbology {
2✔
366
            SymbologyDbType {
367
                raster: Some(raster),
20✔
368
                point: None,
20✔
369
                line: None,
20✔
370
                polygon: None,
20✔
371
            } => Ok(Self::Raster(raster)),
20✔
372
            SymbologyDbType {
373
                raster: None,
374
                point: Some(point),
8✔
375
                line: None,
8✔
376
                polygon: None,
8✔
377
            } => Ok(Self::Point(point)),
8✔
378
            SymbologyDbType {
379
                raster: None,
380
                point: None,
381
                line: Some(line),
1✔
382
                polygon: None,
1✔
383
            } => Ok(Self::Line(line)),
1✔
384
            SymbologyDbType {
385
                raster: None,
386
                point: None,
387
                line: None,
388
                polygon: Some(polygon),
1✔
389
            } => Ok(Self::Polygon(polygon)),
1✔
390
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
391
        }
392
    }
30✔
393
}
394

395
#[derive(Debug, ToSql, FromSql)]
3,730✔
396
#[postgres(name = "Measurement")]
397
pub struct MeasurementDbType {
398
    continuous: Option<ContinuousMeasurement>,
399
    classification: Option<ClassificationMeasurementDbType>,
400
}
401

402
#[derive(Debug, ToSql, FromSql)]
3,454✔
403
struct SmallintTextKeyValue {
404
    key: i16,
405
    value: String,
406
}
407

408
#[derive(Debug, ToSql, FromSql)]
3,386✔
409
#[postgres(name = "ClassificationMeasurement")]
410
pub struct ClassificationMeasurementDbType {
411
    measurement: String,
412
    classes: Vec<SmallintTextKeyValue>,
413
}
414

415
impl From<&Measurement> for MeasurementDbType {
416
    fn from(measurement: &Measurement) -> Self {
219✔
417
        match measurement {
219✔
418
            Measurement::Unitless => Self {
205✔
419
                continuous: None,
205✔
420
                classification: None,
205✔
421
            },
205✔
422
            Measurement::Continuous(measurement) => Self {
11✔
423
                continuous: Some(measurement.clone()),
11✔
424
                classification: None,
11✔
425
            },
11✔
426
            Measurement::Classification(measurement) => Self {
3✔
427
                continuous: None,
3✔
428
                classification: Some(ClassificationMeasurementDbType {
3✔
429
                    measurement: measurement.measurement.clone(),
3✔
430
                    classes: measurement
3✔
431
                        .classes
3✔
432
                        .iter()
3✔
433
                        .map(|(key, value)| SmallintTextKeyValue {
36✔
434
                            key: i16::from(*key),
36✔
435
                            value: value.clone(),
36✔
436
                        })
36✔
437
                        .collect(),
3✔
438
                }),
3✔
439
            },
3✔
440
        }
441
    }
219✔
442
}
443

444
impl TryFrom<MeasurementDbType> for Measurement {
445
    type Error = Error;
446

447
    fn try_from(measurement: MeasurementDbType) -> Result<Self, Self::Error> {
448
        match measurement {
88✔
449
            MeasurementDbType {
450
                continuous: None,
451
                classification: None,
452
            } => Ok(Self::Unitless),
76✔
453
            MeasurementDbType {
454
                continuous: Some(continuous),
10✔
455
                classification: None,
10✔
456
            } => Ok(Self::Continuous(continuous)),
10✔
457
            MeasurementDbType {
458
                continuous: None,
459
                classification: Some(classification),
2✔
460
            } => {
2✔
461
                let mut classes = HashMap::with_capacity(classification.classes.len());
2✔
462
                for SmallintTextKeyValue { key, value } in classification.classes {
21✔
463
                    classes.insert(
464
                        u8::try_from(key).map_err(|_| Error::UnexpectedInvalidDbTypeConversion)?,
19✔
465
                        value,
19✔
466
                    );
467
                }
468

469
                Ok(Self::Classification(ClassificationMeasurement {
2✔
470
                    measurement: classification.measurement,
2✔
471
                    classes,
2✔
472
                }))
2✔
473
            }
474
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
475
        }
476
    }
88✔
477
}
478

479
#[derive(Debug, FromSql, ToSql)]
1,652✔
480
#[postgres(name = "VectorColumnInfo")]
481
pub struct VectorColumnInfoDbType {
482
    pub column: String,
483
    pub data_type: FeatureDataType,
484
    pub measurement: Measurement,
485
}
486

487
#[derive(Debug, FromSql, ToSql)]
2,478✔
488
#[postgres(name = "VectorResultDescriptor")]
489
pub struct VectorResultDescriptorDbType {
490
    pub data_type: VectorDataType,
491
    pub spatial_reference: SpatialReferenceOption,
492
    pub columns: Vec<VectorColumnInfoDbType>,
493
    pub time: Option<TimeInterval>,
494
    pub bbox: Option<BoundingBox2D>,
495
}
496

497
impl From<&VectorResultDescriptor> for VectorResultDescriptorDbType {
498
    fn from(result_descriptor: &VectorResultDescriptor) -> Self {
56✔
499
        Self {
56✔
500
            data_type: result_descriptor.data_type,
56✔
501
            spatial_reference: result_descriptor.spatial_reference,
56✔
502
            columns: result_descriptor
56✔
503
                .columns
56✔
504
                .iter()
56✔
505
                .map(|(column, info)| VectorColumnInfoDbType {
74✔
506
                    column: column.clone(),
74✔
507
                    data_type: info.data_type,
74✔
508
                    measurement: info.measurement.clone(),
74✔
509
                })
74✔
510
                .collect(),
56✔
511
            time: result_descriptor.time,
56✔
512
            bbox: result_descriptor.bbox,
56✔
513
        }
56✔
514
    }
56✔
515
}
516

517
impl TryFrom<VectorResultDescriptorDbType> for VectorResultDescriptor {
518
    type Error = Error;
519

520
    fn try_from(result_descriptor: VectorResultDescriptorDbType) -> Result<Self, Self::Error> {
32✔
521
        Ok(Self {
32✔
522
            data_type: result_descriptor.data_type,
32✔
523
            spatial_reference: result_descriptor.spatial_reference,
32✔
524
            columns: result_descriptor
32✔
525
                .columns
32✔
526
                .into_iter()
32✔
527
                .map(|info| {
39✔
528
                    (
39✔
529
                        info.column,
39✔
530
                        VectorColumnInfo {
39✔
531
                            data_type: info.data_type,
39✔
532
                            measurement: info.measurement,
39✔
533
                        },
39✔
534
                    )
39✔
535
                })
39✔
536
                .collect(),
32✔
537
            time: result_descriptor.time,
32✔
538
            bbox: result_descriptor.bbox,
32✔
539
        })
32✔
540
    }
32✔
541
}
542

543
#[derive(Debug, ToSql, FromSql)]
468✔
544
#[postgres(name = "ResultDescriptor")]
545
pub struct TypedResultDescriptorDbType {
546
    raster: Option<RasterResultDescriptor>,
547
    vector: Option<VectorResultDescriptor>,
548
    plot: Option<PlotResultDescriptor>,
549
}
550

551
impl From<&TypedResultDescriptor> for TypedResultDescriptorDbType {
552
    fn from(result_descriptor: &TypedResultDescriptor) -> Self {
94✔
553
        match result_descriptor {
94✔
554
            TypedResultDescriptor::Raster(raster) => Self {
67✔
555
                raster: Some(raster.clone()),
67✔
556
                vector: None,
67✔
557
                plot: None,
67✔
558
            },
67✔
559
            TypedResultDescriptor::Vector(vector) => Self {
26✔
560
                raster: None,
26✔
561
                vector: Some(vector.clone()),
26✔
562
                plot: None,
26✔
563
            },
26✔
564
            TypedResultDescriptor::Plot(plot) => Self {
1✔
565
                raster: None,
1✔
566
                vector: None,
1✔
567
                plot: Some(*plot),
1✔
568
            },
1✔
569
        }
570
    }
94✔
571
}
572

573
impl TryFrom<TypedResultDescriptorDbType> for TypedResultDescriptor {
574
    type Error = Error;
575

576
    fn try_from(result_descriptor: TypedResultDescriptorDbType) -> Result<Self, Self::Error> {
577
        match result_descriptor {
18✔
578
            TypedResultDescriptorDbType {
579
                raster: Some(raster),
5✔
580
                vector: None,
5✔
581
                plot: None,
5✔
582
            } => Ok(Self::Raster(raster)),
5✔
583
            TypedResultDescriptorDbType {
584
                raster: None,
585
                vector: Some(vector),
17✔
586
                plot: None,
17✔
587
            } => Ok(Self::Vector(vector)),
17✔
588
            TypedResultDescriptorDbType {
589
                raster: None,
590
                vector: None,
591
                plot: Some(plot),
1✔
592
            } => Ok(Self::Plot(plot)),
1✔
593
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
594
        }
595
    }
23✔
596
}
597

598
#[derive(Debug, PartialEq, ToSql, FromSql)]
600✔
599
pub struct TextTextKeyValue {
600
    key: String,
601
    value: String,
602
}
603

604
#[derive(Debug, PartialEq, ToSql, FromSql)]
187✔
605
#[postgres(transparent)]
606
pub struct HashMapTextTextDbType(pub Vec<TextTextKeyValue>);
607

608
impl From<&HashMap<String, String>> for HashMapTextTextDbType {
609
    fn from(map: &HashMap<String, String>) -> Self {
25✔
610
        Self(
25✔
611
            map.iter()
25✔
612
                .map(|(key, value)| TextTextKeyValue {
25✔
613
                    key: key.clone(),
12✔
614
                    value: value.clone(),
12✔
615
                })
25✔
616
                .collect(),
25✔
617
        )
25✔
618
    }
25✔
619
}
620

621
impl<S: std::hash::BuildHasher + std::default::Default> From<HashMapTextTextDbType>
622
    for HashMap<String, String, S>
623
{
624
    fn from(map: HashMapTextTextDbType) -> Self {
19✔
625
        map.0
19✔
626
            .into_iter()
19✔
627
            .map(|TextTextKeyValue { key, value }| (key, value))
19✔
628
            .collect()
19✔
629
    }
19✔
630
}
631

632
#[derive(Debug, ToSql, FromSql)]
1,958✔
633
#[postgres(name = "OgrSourceTimeFormat")]
634
pub struct OgrSourceTimeFormatDbType {
635
    custom: Option<OgrSourceTimeFormatCustomDbType>,
636
    unix_time_stamp: Option<OgrSourceTimeFormatUnixTimeStampDbType>,
637
}
638

639
#[derive(Debug, ToSql, FromSql)]
1,911✔
640
#[postgres(name = "OgrSourceTimeFormatCustom")]
641
pub struct OgrSourceTimeFormatCustomDbType {
642
    custom_format: DateTimeParseFormat,
643
}
644

645
#[derive(Debug, ToSql, FromSql)]
1,906✔
646
#[postgres(name = "OgrSourceTimeFormatUnixTimeStamp")]
647
pub struct OgrSourceTimeFormatUnixTimeStampDbType {
648
    timestamp_type: UnixTimeStampType,
649
    fmt: DateTimeParseFormat,
650
}
651

652
impl From<&OgrSourceTimeFormat> for OgrSourceTimeFormatDbType {
653
    fn from(other: &OgrSourceTimeFormat) -> Self {
21✔
654
        match other {
21✔
655
            OgrSourceTimeFormat::Custom { custom_format } => Self {
3✔
656
                custom: Some(OgrSourceTimeFormatCustomDbType {
3✔
657
                    custom_format: custom_format.clone(),
3✔
658
                }),
3✔
659
                unix_time_stamp: None,
3✔
660
            },
3✔
661
            OgrSourceTimeFormat::UnixTimeStamp {
662
                timestamp_type,
1✔
663
                fmt,
1✔
664
            } => Self {
1✔
665
                custom: None,
1✔
666
                unix_time_stamp: Some(OgrSourceTimeFormatUnixTimeStampDbType {
1✔
667
                    timestamp_type: *timestamp_type,
1✔
668
                    fmt: fmt.clone(),
1✔
669
                }),
1✔
670
            },
1✔
671
            OgrSourceTimeFormat::Auto => Self {
17✔
672
                custom: None,
17✔
673
                unix_time_stamp: None,
17✔
674
            },
17✔
675
        }
676
    }
21✔
677
}
678

679
impl TryFrom<OgrSourceTimeFormatDbType> for OgrSourceTimeFormat {
680
    type Error = Error;
681

682
    fn try_from(other: OgrSourceTimeFormatDbType) -> Result<Self, Self::Error> {
683
        match other {
14✔
684
            OgrSourceTimeFormatDbType {
685
                custom: Some(custom),
3✔
686
                unix_time_stamp: None,
3✔
687
            } => Ok(Self::Custom {
3✔
688
                custom_format: custom.custom_format,
3✔
689
            }),
3✔
690
            OgrSourceTimeFormatDbType {
691
                custom: None,
692
                unix_time_stamp: Some(unix_time_stamp),
1✔
693
            } => Ok(Self::UnixTimeStamp {
1✔
694
                timestamp_type: unix_time_stamp.timestamp_type,
1✔
695
                fmt: unix_time_stamp.fmt,
1✔
696
            }),
1✔
697
            OgrSourceTimeFormatDbType {
698
                custom: None,
699
                unix_time_stamp: None,
700
            } => Ok(Self::Auto),
10✔
701
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
702
        }
703
    }
14✔
704
}
705

706
#[derive(Debug, ToSql, FromSql)]
652✔
707
#[postgres(name = "OgrSourceDurationSpec")]
708
pub struct OgrSourceDurationSpecDbType {
709
    infinite: bool,
710
    zero: bool,
711
    value: Option<TimeStep>,
712
}
713

714
impl From<&OgrSourceDurationSpec> for OgrSourceDurationSpecDbType {
715
    fn from(other: &OgrSourceDurationSpec) -> Self {
16✔
716
        match other {
16✔
717
            OgrSourceDurationSpec::Infinite => Self {
1✔
718
                infinite: true,
1✔
719
                zero: false,
1✔
720
                value: None,
1✔
721
            },
1✔
722
            OgrSourceDurationSpec::Zero => Self {
14✔
723
                infinite: false,
14✔
724
                zero: true,
14✔
725
                value: None,
14✔
726
            },
14✔
727
            OgrSourceDurationSpec::Value(value) => Self {
1✔
728
                infinite: false,
1✔
729
                zero: false,
1✔
730
                value: Some(*value),
1✔
731
            },
1✔
732
        }
733
    }
16✔
734
}
735

736
impl TryFrom<OgrSourceDurationSpecDbType> for OgrSourceDurationSpec {
737
    type Error = Error;
738

739
    fn try_from(other: OgrSourceDurationSpecDbType) -> Result<Self, Self::Error> {
740
        match other {
9✔
741
            OgrSourceDurationSpecDbType {
742
                infinite: true,
743
                zero: false,
744
                value: None,
745
            } => Ok(Self::Infinite),
1✔
746
            OgrSourceDurationSpecDbType {
747
                infinite: false,
748
                zero: true,
749
                value: None,
750
            } => Ok(Self::Zero),
7✔
751
            OgrSourceDurationSpecDbType {
752
                infinite: false,
753
                zero: false,
754
                value: Some(value),
1✔
755
            } => Ok(Self::Value(value)),
1✔
756
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
757
        }
758
    }
9✔
759
}
760

761
#[derive(Debug, ToSql, FromSql)]
628✔
762
#[postgres(name = "OgrSourceDatasetTimeType")]
763
pub struct OgrSourceDatasetTimeTypeDbType {
764
    start: Option<OgrSourceDatasetTimeTypeStartDbType>,
765
    start_end: Option<OgrSourceDatasetTimeTypeStartEndDbType>,
766
    start_duration: Option<OgrSourceDatasetTimeTypeStartDurationDbType>,
767
}
768

769
#[derive(Debug, ToSql, FromSql)]
628✔
770
#[postgres(name = "OgrSourceDatasetTimeTypeStart")]
771
pub struct OgrSourceDatasetTimeTypeStartDbType {
772
    start_field: String,
773
    start_format: OgrSourceTimeFormat,
774
    duration: OgrSourceDurationSpec,
775
}
776

777
#[derive(Debug, ToSql, FromSql)]
785✔
778
#[postgres(name = "OgrSourceDatasetTimeTypeStartEnd")]
779
pub struct OgrSourceDatasetTimeTypeStartEndDbType {
780
    start_field: String,
781
    start_format: OgrSourceTimeFormat,
782
    end_field: String,
783
    end_format: OgrSourceTimeFormat,
784
}
785

786
#[derive(Debug, ToSql, FromSql)]
628✔
787
#[postgres(name = "OgrSourceDatasetTimeTypeStartDuration")]
788
pub struct OgrSourceDatasetTimeTypeStartDurationDbType {
789
    start_field: String,
790
    start_format: OgrSourceTimeFormat,
791
    duration_field: String,
792
}
793

794
impl From<&OgrSourceDatasetTimeType> for OgrSourceDatasetTimeTypeDbType {
795
    fn from(other: &OgrSourceDatasetTimeType) -> Self {
32✔
796
        match other {
32✔
797
            OgrSourceDatasetTimeType::None => Self {
16✔
798
                start: None,
16✔
799
                start_end: None,
16✔
800
                start_duration: None,
16✔
801
            },
16✔
802
            OgrSourceDatasetTimeType::Start {
803
                start_field,
13✔
804
                start_format,
13✔
805
                duration,
13✔
806
            } => Self {
13✔
807
                start: Some(OgrSourceDatasetTimeTypeStartDbType {
13✔
808
                    start_field: start_field.clone(),
13✔
809
                    start_format: start_format.clone(),
13✔
810
                    duration: *duration,
13✔
811
                }),
13✔
812
                start_end: None,
13✔
813
                start_duration: None,
13✔
814
            },
13✔
815
            OgrSourceDatasetTimeType::StartEnd {
816
                start_field,
2✔
817
                start_format,
2✔
818
                end_field,
2✔
819
                end_format,
2✔
820
            } => Self {
2✔
821
                start: None,
2✔
822
                start_end: Some(OgrSourceDatasetTimeTypeStartEndDbType {
2✔
823
                    start_field: start_field.clone(),
2✔
824
                    start_format: start_format.clone(),
2✔
825
                    end_field: end_field.clone(),
2✔
826
                    end_format: end_format.clone(),
2✔
827
                }),
2✔
828
                start_duration: None,
2✔
829
            },
2✔
830
            OgrSourceDatasetTimeType::StartDuration {
831
                start_field,
1✔
832
                start_format,
1✔
833
                duration_field,
1✔
834
            } => Self {
1✔
835
                start: None,
1✔
836
                start_end: None,
1✔
837
                start_duration: Some(OgrSourceDatasetTimeTypeStartDurationDbType {
1✔
838
                    start_field: start_field.clone(),
1✔
839
                    start_format: start_format.clone(),
1✔
840
                    duration_field: duration_field.clone(),
1✔
841
                }),
1✔
842
            },
1✔
843
        }
844
    }
32✔
845
}
846

847
impl TryFrom<OgrSourceDatasetTimeTypeDbType> for OgrSourceDatasetTimeType {
848
    type Error = Error;
849

850
    fn try_from(other: OgrSourceDatasetTimeTypeDbType) -> Result<Self, Self::Error> {
851
        match other {
11✔
852
            OgrSourceDatasetTimeTypeDbType {
853
                start: None,
854
                start_end: None,
855
                start_duration: None,
856
            } => Ok(Self::None),
8✔
857
            OgrSourceDatasetTimeTypeDbType {
858
                start: Some(start),
6✔
859
                start_end: None,
6✔
860
                start_duration: None,
6✔
861
            } => Ok(Self::Start {
6✔
862
                start_field: start.start_field,
6✔
863
                start_format: start.start_format,
6✔
864
                duration: start.duration,
6✔
865
            }),
6✔
866
            OgrSourceDatasetTimeTypeDbType {
867
                start: None,
868
                start_end: Some(start_end),
2✔
869
                start_duration: None,
2✔
870
            } => Ok(Self::StartEnd {
2✔
871
                start_field: start_end.start_field,
2✔
872
                start_format: start_end.start_format,
2✔
873
                end_field: start_end.end_field,
2✔
874
                end_format: start_end.end_format,
2✔
875
            }),
2✔
876
            OgrSourceDatasetTimeTypeDbType {
877
                start: None,
878
                start_end: None,
879
                start_duration: Some(start_duration),
1✔
880
            } => Ok(Self::StartDuration {
1✔
881
                start_field: start_duration.start_field,
1✔
882
                start_format: start_duration.start_format,
1✔
883
                duration_field: start_duration.duration_field,
1✔
884
            }),
1✔
885
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
886
        }
887
    }
17✔
888
}
889

890
#[derive(Debug, ToSql, FromSql)]
480✔
891
#[postgres(name = "FormatSpecifics")]
892
pub struct FormatSpecificsDbType {
893
    csv: Option<FormatSpecificsCsvDbType>,
894
}
895

896
#[derive(Debug, ToSql, FromSql)]
480✔
897
#[postgres(name = "FormatSpecificsCsv")]
898
pub struct FormatSpecificsCsvDbType {
899
    header: CsvHeader,
900
}
901

902
impl From<&FormatSpecifics> for FormatSpecificsDbType {
903
    fn from(other: &FormatSpecifics) -> Self {
14✔
904
        match other {
14✔
905
            FormatSpecifics::Csv { header } => Self {
14✔
906
                csv: Some(FormatSpecificsCsvDbType { header: *header }),
14✔
907
            },
14✔
908
        }
14✔
909
    }
14✔
910
}
911

912
impl TryFrom<FormatSpecificsDbType> for FormatSpecifics {
913
    type Error = Error;
914

915
    fn try_from(other: FormatSpecificsDbType) -> Result<Self, Self::Error> {
7✔
916
        match other {
7✔
917
            FormatSpecificsDbType {
918
                csv: Some(FormatSpecificsCsvDbType { header }),
7✔
919
            } => Ok(Self::Csv { header }),
7✔
920
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
921
        }
922
    }
7✔
923
}
924

925
#[derive(Debug, ToSql, FromSql)]
1,510✔
926
#[postgres(name = "OgrSourceColumnSpec")]
927
pub struct OgrSourceColumnSpecDbType {
928
    pub format_specifics: Option<FormatSpecifics>,
929
    pub x: String,
930
    pub y: Option<String>,
931
    pub int: Vec<String>,
932
    pub float: Vec<String>,
933
    pub text: Vec<String>,
934
    pub bool: Vec<String>,
935
    pub datetime: Vec<String>,
936
    pub rename: Option<HashMapTextTextDbType>,
937
}
938

939
impl From<&OgrSourceColumnSpec> for OgrSourceColumnSpecDbType {
940
    fn from(other: &OgrSourceColumnSpec) -> Self {
18✔
941
        Self {
18✔
942
            format_specifics: other.format_specifics.clone(),
18✔
943
            x: other.x.clone(),
18✔
944
            y: other.y.clone(),
18✔
945
            int: other.int.clone(),
18✔
946
            float: other.float.clone(),
18✔
947
            text: other.text.clone(),
18✔
948
            bool: other.bool.clone(),
18✔
949
            datetime: other.datetime.clone(),
18✔
950
            rename: other.rename.as_ref().map(Into::into),
18✔
951
        }
18✔
952
    }
18✔
953
}
954

955
impl TryFrom<OgrSourceColumnSpecDbType> for OgrSourceColumnSpec {
956
    type Error = Error;
957

958
    fn try_from(other: OgrSourceColumnSpecDbType) -> Result<Self, Self::Error> {
9✔
959
        Ok(Self {
9✔
960
            format_specifics: other.format_specifics,
9✔
961
            x: other.x,
9✔
962
            y: other.y,
9✔
963
            int: other.int,
9✔
964
            float: other.float,
9✔
965
            text: other.text,
9✔
966
            bool: other.bool,
9✔
967
            datetime: other.datetime,
9✔
968
            rename: other.rename.map(Into::into),
9✔
969
        })
9✔
970
    }
9✔
971
}
972

973
#[derive(Debug)]
×
974
pub struct PolygonRef<'p> {
975
    pub rings: &'p [Vec<Coordinate2D>],
976
}
977

978
#[derive(Debug)]
×
979
pub struct PolygonOwned {
980
    pub rings: Vec<Vec<Coordinate2D>>,
981
}
982

983
impl ToSql for PolygonRef<'_> {
984
    fn to_sql(
4✔
985
        &self,
4✔
986
        ty: &postgres_types::Type,
4✔
987
        w: &mut bytes::BytesMut,
4✔
988
    ) -> Result<postgres_types::IsNull, Box<dyn std::error::Error + Sync + Send>> {
4✔
989
        let postgres_types::Kind::Domain(domain_type) = ty.kind() else {
4✔
990
            panic!("expected domain type");
×
991
        };
992

993
        let postgres_types::Kind::Array(member_type) = domain_type.kind() else {
4✔
994
            panic!("expected array type");
×
995
        };
996

997
        let dimension = postgres_protocol::types::ArrayDimension {
4✔
998
            len: self.rings.len() as i32,
4✔
999
            lower_bound: 1, // arrays are one-indexed
4✔
1000
        };
4✔
1001

4✔
1002
        postgres_protocol::types::array_to_sql(
4✔
1003
            Some(dimension),
4✔
1004
            member_type.oid(),
4✔
1005
            self.rings.iter(),
4✔
1006
            |coordinates, w| {
4✔
1007
                postgres_protocol::types::path_to_sql(
8✔
1008
                    true,
8✔
1009
                    coordinates.iter().map(|p| (p.x, p.y)),
32✔
1010
                    w,
8✔
1011
                )?;
8✔
1012

1013
                Ok(postgres_protocol::IsNull::No)
8✔
1014
            },
8✔
1015
            w,
4✔
1016
        )?;
4✔
1017

1018
        Ok(postgres_types::IsNull::No)
4✔
1019
    }
4✔
1020

1021
    fn accepts(ty: &postgres_types::Type) -> bool {
1✔
1022
        if ty.name() != "Polygon" {
1✔
1023
            return false;
×
1024
        }
1✔
1025

1026
        let postgres_types::Kind::Domain(inner_type) = ty.kind() else {
1✔
1027
            return false;
×
1028
        };
1029

1030
        let postgres_types::Kind::Array(inner_type) = inner_type.kind() else {
1✔
1031
            return false;
×
1032
        };
1033

1034
        matches!(inner_type, &postgres_types::Type::PATH)
1✔
1035
    }
1✔
1036

1037
    postgres_types::to_sql_checked!();
1038
}
1039

1040
impl<'a> FromSql<'a> for PolygonOwned {
1041
    fn from_sql(
4✔
1042
        _ty: &postgres_types::Type,
4✔
1043
        raw: &'a [u8],
4✔
1044
    ) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
4✔
1045
        let array = postgres_protocol::types::array_from_sql(raw)?;
4✔
1046
        if array.dimensions().count()? > 1 {
4✔
1047
            return Err("array contains too many dimensions".into());
×
1048
        }
4✔
1049

1050
        let rings = array
4✔
1051
            .values()
4✔
1052
            .map(|raw| {
8✔
1053
                let Some(raw) = raw else {
8✔
1054
                    return Err("array contains NULL values".into());
×
1055
                };
1056
                let path = postgres_protocol::types::path_from_sql(raw)?;
8✔
1057

1058
                let coordinates = path
8✔
1059
                    .points()
8✔
1060
                    .map(|point| {
32✔
1061
                        Ok(Coordinate2D {
32✔
1062
                            x: point.x(),
32✔
1063
                            y: point.y(),
32✔
1064
                        })
32✔
1065
                    })
32✔
1066
                    .collect()?;
8✔
1067
                Ok(coordinates)
8✔
1068
            })
8✔
1069
            .collect()?;
4✔
1070

1071
        Ok(Self { rings })
4✔
1072
    }
4✔
1073

1074
    fn accepts(ty: &postgres_types::Type) -> bool {
×
1075
        if ty.name() != "Polygon" {
×
1076
            return false;
×
1077
        }
×
1078

1079
        let postgres_types::Kind::Domain(inner_type) = ty.kind() else {
×
1080
            return false;
×
1081
        };
1082

1083
        let postgres_types::Kind::Array(inner_type) = inner_type.kind() else {
×
1084
            return false;
×
1085
        };
1086

1087
        matches!(inner_type, &postgres_types::Type::PATH)
×
1088
    }
×
1089
}
1090

1091
#[derive(Debug, ToSql, FromSql)]
785✔
1092
#[postgres(name = "TypedGeometry")]
1093
pub struct TypedGeometryDbType {
1094
    data: bool,
1095
    multi_point: Option<MultiPoint>,
1096
    multi_line_string: Option<MultiLineString>,
1097
    multi_polygon: Option<MultiPolygon>,
1098
}
1099

1100
impl From<&TypedGeometry> for TypedGeometryDbType {
1101
    fn from(other: &TypedGeometry) -> Self {
7✔
1102
        match other {
7✔
1103
            TypedGeometry::Data(_) => Self {
1✔
1104
                data: true,
1✔
1105
                multi_point: None,
1✔
1106
                multi_line_string: None,
1✔
1107
                multi_polygon: None,
1✔
1108
            },
1✔
1109
            TypedGeometry::MultiPoint(points) => Self {
4✔
1110
                data: false,
4✔
1111
                multi_point: Some(points.clone()),
4✔
1112
                multi_line_string: None,
4✔
1113
                multi_polygon: None,
4✔
1114
            },
4✔
1115
            TypedGeometry::MultiLineString(lines) => Self {
1✔
1116
                data: false,
1✔
1117
                multi_point: None,
1✔
1118
                multi_line_string: Some(lines.clone()),
1✔
1119
                multi_polygon: None,
1✔
1120
            },
1✔
1121
            TypedGeometry::MultiPolygon(polygons) => Self {
1✔
1122
                data: false,
1✔
1123
                multi_point: None,
1✔
1124
                multi_line_string: None,
1✔
1125
                multi_polygon: Some(polygons.clone()),
1✔
1126
            },
1✔
1127
        }
1128
    }
7✔
1129
}
1130

1131
impl TryFrom<TypedGeometryDbType> for TypedGeometry {
1132
    type Error = Error;
1133

1134
    fn try_from(other: TypedGeometryDbType) -> Result<Self, Self::Error> {
1135
        match other {
2✔
1136
            TypedGeometryDbType {
1137
                data: true,
1138
                multi_point: None,
1139
                multi_line_string: None,
1140
                multi_polygon: None,
1141
            } => Ok(TypedGeometry::Data(NoGeometry)),
1✔
1142
            TypedGeometryDbType {
1143
                data: false,
1144
                multi_point: Some(multi_point),
4✔
1145
                multi_line_string: None,
4✔
1146
                multi_polygon: None,
4✔
1147
            } => Ok(TypedGeometry::MultiPoint(multi_point)),
4✔
1148
            TypedGeometryDbType {
1149
                data: false,
1150
                multi_point: None,
1151
                multi_line_string: Some(multi_line_string),
1✔
1152
                multi_polygon: None,
1✔
1153
            } => Ok(TypedGeometry::MultiLineString(multi_line_string)),
1✔
1154
            TypedGeometryDbType {
1155
                data: false,
1156
                multi_point: None,
1157
                multi_line_string: None,
1158
                multi_polygon: Some(multi_polygon),
1✔
1159
            } => Ok(TypedGeometry::MultiPolygon(multi_polygon)),
1✔
1160
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
1161
        }
1162
    }
7✔
1163
}
1164

1165
#[derive(Debug, ToSql, FromSql)]
1,937✔
1166
#[postgres(name = "OgrSourceDataset")]
1167
pub struct OgrSourceDatasetDbType {
1168
    pub file_name: String,
1169
    pub layer_name: String,
1170
    pub data_type: Option<VectorDataType>,
1171
    pub time: OgrSourceDatasetTimeType,
1172
    pub default_geometry: Option<TypedGeometry>,
1173
    pub columns: Option<OgrSourceColumnSpec>,
1174
    pub force_ogr_time_filter: bool,
1175
    pub force_ogr_spatial_filter: bool,
1176
    pub on_error: OgrSourceErrorSpec,
1177
    pub sql_query: Option<String>,
1178
    pub attribute_query: Option<String>,
1179
    pub cache_ttl: CacheTtlSeconds,
1180
}
1181

1182
impl From<&OgrSourceDataset> for OgrSourceDatasetDbType {
1183
    fn from(other: &OgrSourceDataset) -> Self {
28✔
1184
        Self {
28✔
1185
            file_name: other.file_name.to_string_lossy().to_string(),
28✔
1186
            layer_name: other.layer_name.clone(),
28✔
1187
            data_type: other.data_type,
28✔
1188
            time: other.time.clone(),
28✔
1189
            default_geometry: other.default_geometry.clone(),
28✔
1190
            columns: other.columns.clone(),
28✔
1191
            force_ogr_time_filter: other.force_ogr_time_filter,
28✔
1192
            force_ogr_spatial_filter: other.force_ogr_spatial_filter,
28✔
1193
            on_error: other.on_error,
28✔
1194
            sql_query: other.sql_query.clone(),
28✔
1195
            attribute_query: other.attribute_query.clone(),
28✔
1196
            cache_ttl: other.cache_ttl,
28✔
1197
        }
28✔
1198
    }
28✔
1199
}
1200

1201
impl TryFrom<OgrSourceDatasetDbType> for OgrSourceDataset {
1202
    type Error = Error;
1203

1204
    fn try_from(other: OgrSourceDatasetDbType) -> Result<Self, Self::Error> {
13✔
1205
        Ok(Self {
13✔
1206
            file_name: other.file_name.into(),
13✔
1207
            layer_name: other.layer_name,
13✔
1208
            data_type: other.data_type,
13✔
1209
            time: other.time,
13✔
1210
            default_geometry: other.default_geometry,
13✔
1211
            columns: other.columns,
13✔
1212
            force_ogr_time_filter: other.force_ogr_time_filter,
13✔
1213
            force_ogr_spatial_filter: other.force_ogr_spatial_filter,
13✔
1214
            on_error: other.on_error,
13✔
1215
            sql_query: other.sql_query,
13✔
1216
            attribute_query: other.attribute_query,
13✔
1217
            cache_ttl: other.cache_ttl,
13✔
1218
        })
13✔
1219
    }
13✔
1220
}
1221

1222
#[derive(Debug, ToSql, FromSql)]
489✔
1223
#[postgres(name = "OgrMetaData")]
1224
pub struct OgrMetaDataDbType {
1225
    pub loading_info: OgrSourceDataset,
1226
    pub result_descriptor: VectorResultDescriptor,
1227
}
1228

1229
impl From<&OgrMetaData> for OgrMetaDataDbType {
1230
    fn from(other: &OgrMetaData) -> Self {
27✔
1231
        Self {
27✔
1232
            loading_info: other.loading_info.clone(),
27✔
1233
            result_descriptor: other.result_descriptor.clone(),
27✔
1234
        }
27✔
1235
    }
27✔
1236
}
1237

1238
impl TryFrom<OgrMetaDataDbType> for OgrMetaData {
1239
    type Error = Error;
1240

1241
    fn try_from(other: OgrMetaDataDbType) -> Result<Self, Self::Error> {
12✔
1242
        Ok(Self {
12✔
1243
            loading_info: other.loading_info,
12✔
1244
            result_descriptor: other.result_descriptor,
12✔
1245
            phantom: PhantomData,
12✔
1246
        })
12✔
1247
    }
12✔
1248
}
1249

1250
#[derive(Debug, ToSql, FromSql)]
449✔
1251
#[postgres(name = "MockMetaData")]
1252
pub struct MockMetaDataDbType {
1253
    pub loading_info: MockDatasetDataSourceLoadingInfo,
1254
    pub result_descriptor: VectorResultDescriptor,
1255
}
1256

1257
impl From<&MockMetaData> for MockMetaDataDbType {
1258
    fn from(other: &MockMetaData) -> Self {
2✔
1259
        Self {
2✔
1260
            loading_info: other.loading_info.clone(),
2✔
1261
            result_descriptor: other.result_descriptor.clone(),
2✔
1262
        }
2✔
1263
    }
2✔
1264
}
1265

1266
impl TryFrom<MockMetaDataDbType> for MockMetaData {
1267
    type Error = Error;
1268

1269
    fn try_from(other: MockMetaDataDbType) -> Result<Self, Self::Error> {
2✔
1270
        Ok(Self {
2✔
1271
            loading_info: other.loading_info,
2✔
1272
            result_descriptor: other.result_descriptor,
2✔
1273
            phantom: PhantomData,
2✔
1274
        })
2✔
1275
    }
2✔
1276
}
1277

1278
#[derive(Debug, ToSql, FromSql)]
7,080✔
1279
#[postgres(name = "GdalDatasetParameters")]
1280
pub struct GdalDatasetParametersDbType {
1281
    pub file_path: String,
1282
    pub rasterband_channel: i64,
1283
    pub geo_transform: GdalDatasetGeoTransform,
1284
    pub width: i64,
1285
    pub height: i64,
1286
    pub file_not_found_handling: FileNotFoundHandling,
1287
    pub no_data_value: Option<f64>,
1288
    pub properties_mapping: Option<Vec<GdalMetadataMapping>>,
1289
    pub gdal_open_options: Option<Vec<String>>,
1290
    pub gdal_config_options: Option<Vec<GdalConfigOption>>,
1291
    pub allow_alphaband_as_mask: bool,
1292
}
1293

1294
impl From<&GdalDatasetParameters> for GdalDatasetParametersDbType {
1295
    fn from(other: &GdalDatasetParameters) -> Self {
75✔
1296
        Self {
75✔
1297
            file_path: other.file_path.to_string_lossy().to_string(),
75✔
1298
            rasterband_channel: other.rasterband_channel as i64,
75✔
1299
            geo_transform: other.geo_transform,
75✔
1300
            width: other.width as i64,
75✔
1301
            height: other.height as i64,
75✔
1302
            file_not_found_handling: other.file_not_found_handling,
75✔
1303
            no_data_value: other.no_data_value,
75✔
1304
            properties_mapping: other.properties_mapping.clone(),
75✔
1305
            gdal_open_options: other.gdal_open_options.clone(),
75✔
1306
            gdal_config_options: other.gdal_config_options.clone(),
75✔
1307
            allow_alphaband_as_mask: other.allow_alphaband_as_mask,
75✔
1308
        }
75✔
1309
    }
75✔
1310
}
1311

1312
impl TryFrom<GdalDatasetParametersDbType> for GdalDatasetParameters {
1313
    type Error = Error;
1314

1315
    fn try_from(other: GdalDatasetParametersDbType) -> Result<Self, Self::Error> {
41✔
1316
        Ok(Self {
41✔
1317
            file_path: other.file_path.into(),
41✔
1318
            rasterband_channel: other.rasterband_channel as usize,
41✔
1319
            geo_transform: other.geo_transform,
41✔
1320
            width: other.width as usize,
41✔
1321
            height: other.height as usize,
41✔
1322
            file_not_found_handling: other.file_not_found_handling,
41✔
1323
            no_data_value: other.no_data_value,
41✔
1324
            properties_mapping: other.properties_mapping,
41✔
1325
            gdal_open_options: other.gdal_open_options,
41✔
1326
            gdal_config_options: other.gdal_config_options,
41✔
1327
            allow_alphaband_as_mask: other.allow_alphaband_as_mask,
41✔
1328
        })
41✔
1329
    }
41✔
1330
}
1331

1332
#[derive(Debug, ToSql, FromSql, PartialEq)]
536✔
1333
pub struct TextGdalSourceTimePlaceholderKeyValue {
1334
    pub key: String,
1335
    pub value: GdalSourceTimePlaceholder,
1336
}
1337

1338
#[derive(Debug, ToSql, FromSql)]
1,029✔
1339
#[postgres(name = "GdalMetaDataRegular")]
1340
pub struct GdalMetaDataRegularDbType {
1341
    pub result_descriptor: RasterResultDescriptor,
1342
    pub params: GdalDatasetParameters,
1343
    pub time_placeholders: Vec<TextGdalSourceTimePlaceholderKeyValue>,
1344
    pub data_time: TimeInterval,
1345
    pub step: TimeStep,
1346
    pub cache_ttl: CacheTtlSeconds,
1347
}
1348

1349
impl From<&GdalMetaDataRegular> for GdalMetaDataRegularDbType {
1350
    fn from(other: &GdalMetaDataRegular) -> Self {
58✔
1351
        Self {
58✔
1352
            result_descriptor: other.result_descriptor.clone(),
58✔
1353
            params: other.params.clone(),
58✔
1354
            time_placeholders: other
58✔
1355
                .time_placeholders
58✔
1356
                .iter()
58✔
1357
                .map(|(key, value)| TextGdalSourceTimePlaceholderKeyValue {
58✔
1358
                    key: key.clone(),
56✔
1359
                    value: value.clone(),
56✔
1360
                })
58✔
1361
                .collect(),
58✔
1362
            data_time: other.data_time,
58✔
1363
            step: other.step,
58✔
1364
            cache_ttl: other.cache_ttl,
58✔
1365
        }
58✔
1366
    }
58✔
1367
}
1368

1369
impl TryFrom<GdalMetaDataRegularDbType> for GdalMetaDataRegular {
1370
    type Error = Error;
1371

1372
    fn try_from(other: GdalMetaDataRegularDbType) -> Result<Self, Self::Error> {
24✔
1373
        Ok(Self {
24✔
1374
            result_descriptor: other.result_descriptor,
24✔
1375
            params: other.params,
24✔
1376
            time_placeholders: other
24✔
1377
                .time_placeholders
24✔
1378
                .iter()
24✔
1379
                .map(|item| (item.key.clone(), item.value.clone()))
24✔
1380
                .collect(),
24✔
1381
            data_time: other.data_time,
24✔
1382
            step: other.step,
24✔
1383
            cache_ttl: other.cache_ttl,
24✔
1384
        })
24✔
1385
    }
24✔
1386
}
1387

1388
#[derive(Debug, ToSql, FromSql)]
1,176✔
1389
#[postgres(name = "GdalMetadataNetCdfCf")]
1390
pub struct GdalMetadataNetCdfCfDbType {
1391
    pub result_descriptor: RasterResultDescriptor,
1392
    pub params: GdalDatasetParameters,
1393
    pub start: TimeInstance,
1394
    pub end: TimeInstance,
1395
    pub step: TimeStep,
1396
    pub band_offset: i64,
1397
    pub cache_ttl: CacheTtlSeconds,
1398
}
1399

1400
impl From<&GdalMetadataNetCdfCf> for GdalMetadataNetCdfCfDbType {
1401
    fn from(other: &GdalMetadataNetCdfCf) -> Self {
4✔
1402
        Self {
4✔
1403
            result_descriptor: other.result_descriptor.clone(),
4✔
1404
            params: other.params.clone(),
4✔
1405
            start: other.start,
4✔
1406
            end: other.end,
4✔
1407
            step: other.step,
4✔
1408
            band_offset: other.band_offset as i64,
4✔
1409
            cache_ttl: other.cache_ttl,
4✔
1410
        }
4✔
1411
    }
4✔
1412
}
1413

1414
impl TryFrom<GdalMetadataNetCdfCfDbType> for GdalMetadataNetCdfCf {
1415
    type Error = Error;
1416

1417
    fn try_from(other: GdalMetadataNetCdfCfDbType) -> Result<Self, Self::Error> {
4✔
1418
        Ok(Self {
4✔
1419
            result_descriptor: other.result_descriptor,
4✔
1420
            params: other.params,
4✔
1421
            start: other.start,
4✔
1422
            end: other.end,
4✔
1423
            step: other.step,
4✔
1424
            band_offset: other.band_offset as usize,
4✔
1425
            cache_ttl: other.cache_ttl,
4✔
1426
        })
4✔
1427
    }
4✔
1428
}
1429

1430
#[derive(Debug, ToSql, FromSql)]
1,015✔
1431
#[postgres(name = "MetaDataDefinition")]
1432
pub struct MetaDataDefinitionDbType {
1433
    mock_meta_data: Option<MockMetaData>,
1434
    ogr_meta_data: Option<OgrMetaData>,
1435
    gdal_meta_data_regular: Option<GdalMetaDataRegular>,
1436
    gdal_static: Option<GdalMetaDataStatic>,
1437
    gdal_metadata_net_cdf_cf: Option<GdalMetadataNetCdfCf>,
1438
    gdal_meta_data_list: Option<GdalMetaDataList>,
1439
}
1440

1441
impl From<&MetaDataDefinition> for MetaDataDefinitionDbType {
1442
    fn from(other: &MetaDataDefinition) -> Self {
97✔
1443
        match other {
97✔
1444
            MetaDataDefinition::MockMetaData(meta_data) => Self {
1✔
1445
                mock_meta_data: Some(meta_data.clone().into()),
1✔
1446
                ogr_meta_data: None,
1✔
1447
                gdal_meta_data_regular: None,
1✔
1448
                gdal_static: None,
1✔
1449
                gdal_metadata_net_cdf_cf: None,
1✔
1450
                gdal_meta_data_list: None,
1✔
1451
            },
1✔
1452
            MetaDataDefinition::OgrMetaData(meta_data) => Self {
26✔
1453
                mock_meta_data: None,
26✔
1454
                ogr_meta_data: Some(meta_data.clone().into()),
26✔
1455
                gdal_meta_data_regular: None,
26✔
1456
                gdal_static: None,
26✔
1457
                gdal_metadata_net_cdf_cf: None,
26✔
1458
                gdal_meta_data_list: None,
26✔
1459
            },
26✔
1460
            MetaDataDefinition::GdalMetaDataRegular(meta_data) => Self {
57✔
1461
                mock_meta_data: None,
57✔
1462
                ogr_meta_data: None,
57✔
1463
                gdal_meta_data_regular: Some(meta_data.clone().into()),
57✔
1464
                gdal_static: None,
57✔
1465
                gdal_metadata_net_cdf_cf: None,
57✔
1466
                gdal_meta_data_list: None,
57✔
1467
            },
57✔
1468
            MetaDataDefinition::GdalStatic(meta_data) => Self {
5✔
1469
                mock_meta_data: None,
5✔
1470
                ogr_meta_data: None,
5✔
1471
                gdal_meta_data_regular: None,
5✔
1472
                gdal_static: Some(meta_data.clone().into()),
5✔
1473
                gdal_metadata_net_cdf_cf: None,
5✔
1474
                gdal_meta_data_list: None,
5✔
1475
            },
5✔
1476
            MetaDataDefinition::GdalMetadataNetCdfCf(meta_data) => Self {
3✔
1477
                mock_meta_data: None,
3✔
1478
                ogr_meta_data: None,
3✔
1479
                gdal_meta_data_regular: None,
3✔
1480
                gdal_static: None,
3✔
1481
                gdal_metadata_net_cdf_cf: Some(meta_data.clone().into()),
3✔
1482
                gdal_meta_data_list: None,
3✔
1483
            },
3✔
1484
            MetaDataDefinition::GdalMetaDataList(meta_data) => Self {
5✔
1485
                mock_meta_data: None,
5✔
1486
                ogr_meta_data: None,
5✔
1487
                gdal_meta_data_regular: None,
5✔
1488
                gdal_static: None,
5✔
1489
                gdal_metadata_net_cdf_cf: None,
5✔
1490
                gdal_meta_data_list: Some(meta_data.clone().into()),
5✔
1491
            },
5✔
1492
        }
1493
    }
97✔
1494
}
1495

1496
impl TryFrom<MetaDataDefinitionDbType> for MetaDataDefinition {
1497
    type Error = Error;
1498

1499
    fn try_from(other: MetaDataDefinitionDbType) -> Result<Self, Self::Error> {
1500
        match other {
8✔
1501
            MetaDataDefinitionDbType {
1502
                mock_meta_data: Some(meta_data),
1✔
1503
                ogr_meta_data: None,
1✔
1504
                gdal_meta_data_regular: None,
1✔
1505
                gdal_static: None,
1✔
1506
                gdal_metadata_net_cdf_cf: None,
1✔
1507
                gdal_meta_data_list: None,
1✔
1508
            } => Ok(MetaDataDefinition::MockMetaData(meta_data.into())),
1✔
1509
            MetaDataDefinitionDbType {
1510
                mock_meta_data: None,
1511
                ogr_meta_data: Some(meta_data),
11✔
1512
                gdal_meta_data_regular: None,
11✔
1513
                gdal_static: None,
11✔
1514
                gdal_metadata_net_cdf_cf: None,
11✔
1515
                gdal_meta_data_list: None,
11✔
1516
            } => Ok(MetaDataDefinition::OgrMetaData(meta_data.into())),
11✔
1517
            MetaDataDefinitionDbType {
1518
                mock_meta_data: None,
1519
                ogr_meta_data: None,
1520
                gdal_meta_data_regular: Some(meta_data),
23✔
1521
                gdal_static: None,
23✔
1522
                gdal_metadata_net_cdf_cf: None,
23✔
1523
                gdal_meta_data_list: None,
23✔
1524
            } => Ok(MetaDataDefinition::GdalMetaDataRegular(meta_data.into())),
23✔
1525
            MetaDataDefinitionDbType {
1526
                mock_meta_data: None,
1527
                ogr_meta_data: None,
1528
                gdal_meta_data_regular: None,
1529
                gdal_static: Some(meta_data),
5✔
1530
                gdal_metadata_net_cdf_cf: None,
5✔
1531
                gdal_meta_data_list: None,
5✔
1532
            } => Ok(MetaDataDefinition::GdalStatic(meta_data.into())),
5✔
1533
            MetaDataDefinitionDbType {
1534
                mock_meta_data: None,
1535
                ogr_meta_data: None,
1536
                gdal_meta_data_regular: None,
1537
                gdal_static: None,
1538
                gdal_metadata_net_cdf_cf: Some(meta_data),
3✔
1539
                gdal_meta_data_list: None,
3✔
1540
            } => Ok(MetaDataDefinition::GdalMetadataNetCdfCf(meta_data.into())),
3✔
1541
            MetaDataDefinitionDbType {
1542
                mock_meta_data: None,
1543
                ogr_meta_data: None,
1544
                gdal_meta_data_regular: None,
1545
                gdal_static: None,
1546
                gdal_metadata_net_cdf_cf: None,
1547
                gdal_meta_data_list: Some(meta_data),
5✔
1548
            } => Ok(MetaDataDefinition::GdalMetaDataList(meta_data.into())),
5✔
1549
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
1550
        }
1551
    }
48✔
1552
}
1553

1554
#[derive(Debug, ToSql, FromSql)]
651✔
1555
#[postgres(name = "DatabaseConnectionConfig")]
1556
pub struct DatabaseConnectionConfigDbType {
1557
    pub host: String,
1558
    pub port: i32,
1559
    pub database: String,
1560
    pub schema: String,
1561
    pub user: String,
1562
    pub password: String,
1563
}
1564

1565
impl From<&DatabaseConnectionConfig> for DatabaseConnectionConfigDbType {
1566
    fn from(other: &DatabaseConnectionConfig) -> Self {
6✔
1567
        Self {
6✔
1568
            host: other.host.clone(),
6✔
1569
            port: i32::from(other.port),
6✔
1570
            database: other.database.clone(),
6✔
1571
            schema: other.schema.clone(),
6✔
1572
            user: other.user.clone(),
6✔
1573
            password: other.password.clone(),
6✔
1574
        }
6✔
1575
    }
6✔
1576
}
1577

1578
impl TryFrom<DatabaseConnectionConfigDbType> for DatabaseConnectionConfig {
1579
    type Error = Error;
1580

1581
    fn try_from(other: DatabaseConnectionConfigDbType) -> Result<Self, Self::Error> {
6✔
1582
        Ok(Self {
6✔
1583
            host: other.host,
6✔
1584
            port: other.port as u16,
6✔
1585
            database: other.database,
6✔
1586
            schema: other.schema,
6✔
1587
            user: other.user,
6✔
1588
            password: other.password,
6✔
1589
        })
6✔
1590
    }
6✔
1591
}
1592

1593
#[derive(Debug, ToSql, FromSql)]
217✔
1594
#[postgres(name = "GfbioCollectionsDataProviderDefinition")]
1595
pub struct GfbioCollectionsDataProviderDefinitionDbType {
1596
    pub name: String,
1597
    pub collection_api_url: String,
1598
    pub collection_api_auth_token: String,
1599
    pub abcd_db_config: DatabaseConnectionConfig,
1600
    pub pangaea_url: String,
1601
    pub cache_ttl: CacheTtlSeconds,
1602
}
1603

1604
impl From<&GfbioCollectionsDataProviderDefinition>
1605
    for GfbioCollectionsDataProviderDefinitionDbType
1606
{
1607
    fn from(other: &GfbioCollectionsDataProviderDefinition) -> Self {
2✔
1608
        Self {
2✔
1609
            name: other.name.clone(),
2✔
1610
            collection_api_url: other.collection_api_url.clone().into(),
2✔
1611
            collection_api_auth_token: other.collection_api_auth_token.clone(),
2✔
1612
            abcd_db_config: other.abcd_db_config.clone(),
2✔
1613
            pangaea_url: other.pangaea_url.clone().into(),
2✔
1614
            cache_ttl: other.cache_ttl,
2✔
1615
        }
2✔
1616
    }
2✔
1617
}
1618

1619
impl TryFrom<GfbioCollectionsDataProviderDefinitionDbType>
1620
    for GfbioCollectionsDataProviderDefinition
1621
{
1622
    type Error = Error;
1623

1624
    fn try_from(other: GfbioCollectionsDataProviderDefinitionDbType) -> Result<Self, Self::Error> {
2✔
1625
        Ok(Self {
2✔
1626
            name: other.name,
2✔
1627
            collection_api_url: other.collection_api_url.as_str().try_into()?,
2✔
1628
            collection_api_auth_token: other.collection_api_auth_token,
2✔
1629
            abcd_db_config: other.abcd_db_config,
2✔
1630
            pangaea_url: other.pangaea_url.as_str().try_into()?,
2✔
1631
            cache_ttl: other.cache_ttl,
2✔
1632
        })
1633
    }
2✔
1634
}
1635

1636
#[derive(Debug, ToSql, FromSql)]
186✔
1637
#[postgres(name = "EbvPortalDataProviderDefinition")]
1638
pub struct EbvPortalDataProviderDefinitionDbType {
1639
    pub name: String,
1640
    pub path: String,
1641
    pub base_url: String,
1642
    pub overviews: String,
1643
    pub cache_ttl: CacheTtlSeconds,
1644
}
1645

1646
impl From<&EbvPortalDataProviderDefinition> for EbvPortalDataProviderDefinitionDbType {
1647
    fn from(other: &EbvPortalDataProviderDefinition) -> Self {
3✔
1648
        Self {
3✔
1649
            name: other.name.clone(),
3✔
1650
            path: other.path.to_string_lossy().to_string(),
3✔
1651
            base_url: other.base_url.clone().into(),
3✔
1652
            overviews: other.overviews.to_string_lossy().to_string(),
3✔
1653
            cache_ttl: other.cache_ttl,
3✔
1654
        }
3✔
1655
    }
3✔
1656
}
1657

1658
impl TryFrom<EbvPortalDataProviderDefinitionDbType> for EbvPortalDataProviderDefinition {
1659
    type Error = Error;
1660

1661
    fn try_from(other: EbvPortalDataProviderDefinitionDbType) -> Result<Self, Self::Error> {
3✔
1662
        Ok(Self {
3✔
1663
            name: other.name,
3✔
1664
            path: other.path.into(),
3✔
1665
            base_url: other.base_url.as_str().try_into()?,
3✔
1666
            overviews: other.overviews.into(),
3✔
1667
            cache_ttl: other.cache_ttl,
3✔
1668
        })
1669
    }
3✔
1670
}
1671

1672
#[derive(Debug, ToSql, FromSql)]
155✔
1673
#[postgres(name = "NetCdfCfDataProviderDefinition")]
1674
pub struct NetCdfCfDataProviderDefinitionDbType {
1675
    pub name: String,
1676
    pub path: String,
1677
    pub overviews: String,
1678
    pub cache_ttl: CacheTtlSeconds,
1679
}
1680

1681
impl From<&NetCdfCfDataProviderDefinition> for NetCdfCfDataProviderDefinitionDbType {
1682
    fn from(other: &NetCdfCfDataProviderDefinition) -> Self {
7✔
1683
        Self {
7✔
1684
            name: other.name.clone(),
7✔
1685
            path: other.path.to_string_lossy().to_string(),
7✔
1686
            overviews: other.overviews.to_string_lossy().to_string(),
7✔
1687
            cache_ttl: other.cache_ttl,
7✔
1688
        }
7✔
1689
    }
7✔
1690
}
1691

1692
impl TryFrom<NetCdfCfDataProviderDefinitionDbType> for NetCdfCfDataProviderDefinition {
1693
    type Error = Error;
1694

1695
    fn try_from(other: NetCdfCfDataProviderDefinitionDbType) -> Result<Self, Self::Error> {
9✔
1696
        Ok(Self {
9✔
1697
            name: other.name,
9✔
1698
            path: other.path.into(),
9✔
1699
            overviews: other.overviews.into(),
9✔
1700
            cache_ttl: other.cache_ttl,
9✔
1701
        })
9✔
1702
    }
9✔
1703
}
1704

1705
#[derive(Debug, ToSql, FromSql)]
124✔
1706
#[postgres(name = "PangaeaDataProviderDefinition")]
1707
pub struct PangaeaDataProviderDefinitionDbType {
1708
    pub name: String,
1709
    pub base_url: String,
1710
    pub cache_ttl: CacheTtlSeconds,
1711
}
1712

1713
impl From<&PangaeaDataProviderDefinition> for PangaeaDataProviderDefinitionDbType {
1714
    fn from(other: &PangaeaDataProviderDefinition) -> Self {
2✔
1715
        Self {
2✔
1716
            name: other.name.clone(),
2✔
1717
            base_url: other.base_url.clone().into(),
2✔
1718
            cache_ttl: other.cache_ttl,
2✔
1719
        }
2✔
1720
    }
2✔
1721
}
1722

1723
impl TryFrom<PangaeaDataProviderDefinitionDbType> for PangaeaDataProviderDefinition {
1724
    type Error = Error;
1725

1726
    fn try_from(other: PangaeaDataProviderDefinitionDbType) -> Result<Self, Self::Error> {
2✔
1727
        Ok(Self {
2✔
1728
            name: other.name,
2✔
1729
            base_url: other.base_url.as_str().try_into()?,
2✔
1730
            cache_ttl: other.cache_ttl,
2✔
1731
        })
1732
    }
2✔
1733
}
1734

1735
#[derive(Debug, ToSql, FromSql)]
232✔
1736
#[postgres(name = "DataProviderDefinition")]
1737
pub struct TypedDataProviderDefinitionDbType {
1738
    aruna_data_provider_definition: Option<ArunaDataProviderDefinition>,
1739
    gbif_data_provider_definition: Option<GbifDataProviderDefinition>,
1740
    gfbio_abcd_data_provider_definition: Option<GfbioAbcdDataProviderDefinition>,
1741
    gfbio_collections_data_provider_definition: Option<GfbioCollectionsDataProviderDefinition>,
1742
    ebv_portal_data_provider_definition: Option<EbvPortalDataProviderDefinition>,
1743
    net_cdf_cf_data_provider_definition: Option<NetCdfCfDataProviderDefinition>,
1744
    pangaea_data_provider_definition: Option<PangaeaDataProviderDefinition>,
1745
}
1746

1747
impl From<&TypedDataProviderDefinition> for TypedDataProviderDefinitionDbType {
1748
    fn from(other: &TypedDataProviderDefinition) -> Self {
13✔
1749
        match other {
13✔
1750
            TypedDataProviderDefinition::ArunaDataProviderDefinition(data_provider_definition) => {
1✔
1751
                Self {
1✔
1752
                    aruna_data_provider_definition: Some(data_provider_definition.clone()),
1✔
1753
                    gbif_data_provider_definition: None,
1✔
1754
                    gfbio_abcd_data_provider_definition: None,
1✔
1755
                    gfbio_collections_data_provider_definition: None,
1✔
1756
                    ebv_portal_data_provider_definition: None,
1✔
1757
                    net_cdf_cf_data_provider_definition: None,
1✔
1758
                    pangaea_data_provider_definition: None,
1✔
1759
                }
1✔
1760
            }
1761
            TypedDataProviderDefinition::GbifDataProviderDefinition(data_provider_definition) => {
1✔
1762
                Self {
1✔
1763
                    aruna_data_provider_definition: None,
1✔
1764
                    gbif_data_provider_definition: Some(data_provider_definition.clone()),
1✔
1765
                    gfbio_abcd_data_provider_definition: None,
1✔
1766
                    gfbio_collections_data_provider_definition: None,
1✔
1767
                    ebv_portal_data_provider_definition: None,
1✔
1768
                    net_cdf_cf_data_provider_definition: None,
1✔
1769
                    pangaea_data_provider_definition: None,
1✔
1770
                }
1✔
1771
            }
1772
            TypedDataProviderDefinition::GfbioAbcdDataProviderDefinition(
1773
                data_provider_definition,
1✔
1774
            ) => Self {
1✔
1775
                aruna_data_provider_definition: None,
1✔
1776
                gbif_data_provider_definition: None,
1✔
1777
                gfbio_abcd_data_provider_definition: Some(data_provider_definition.clone()),
1✔
1778
                gfbio_collections_data_provider_definition: None,
1✔
1779
                ebv_portal_data_provider_definition: None,
1✔
1780
                net_cdf_cf_data_provider_definition: None,
1✔
1781
                pangaea_data_provider_definition: None,
1✔
1782
            },
1✔
1783
            TypedDataProviderDefinition::GfbioCollectionsDataProviderDefinition(
1784
                data_provider_definition,
1✔
1785
            ) => Self {
1✔
1786
                aruna_data_provider_definition: None,
1✔
1787
                gbif_data_provider_definition: None,
1✔
1788
                gfbio_abcd_data_provider_definition: None,
1✔
1789
                gfbio_collections_data_provider_definition: Some(data_provider_definition.clone()),
1✔
1790
                ebv_portal_data_provider_definition: None,
1✔
1791
                net_cdf_cf_data_provider_definition: None,
1✔
1792
                pangaea_data_provider_definition: None,
1✔
1793
            },
1✔
1794
            TypedDataProviderDefinition::EbvPortalDataProviderDefinition(
1795
                data_provider_definition,
2✔
1796
            ) => Self {
2✔
1797
                aruna_data_provider_definition: None,
2✔
1798
                gbif_data_provider_definition: None,
2✔
1799
                gfbio_abcd_data_provider_definition: None,
2✔
1800
                gfbio_collections_data_provider_definition: None,
2✔
1801
                ebv_portal_data_provider_definition: Some(data_provider_definition.clone()),
2✔
1802
                net_cdf_cf_data_provider_definition: None,
2✔
1803
                pangaea_data_provider_definition: None,
2✔
1804
            },
2✔
1805
            TypedDataProviderDefinition::NetCdfCfDataProviderDefinition(
1806
                data_provider_definition,
6✔
1807
            ) => Self {
6✔
1808
                aruna_data_provider_definition: None,
6✔
1809
                gbif_data_provider_definition: None,
6✔
1810
                gfbio_abcd_data_provider_definition: None,
6✔
1811
                gfbio_collections_data_provider_definition: None,
6✔
1812
                ebv_portal_data_provider_definition: None,
6✔
1813
                net_cdf_cf_data_provider_definition: Some(data_provider_definition.clone()),
6✔
1814
                pangaea_data_provider_definition: None,
6✔
1815
            },
6✔
1816
            TypedDataProviderDefinition::PangaeaDataProviderDefinition(
1817
                data_provider_definition,
1✔
1818
            ) => Self {
1✔
1819
                aruna_data_provider_definition: None,
1✔
1820
                gbif_data_provider_definition: None,
1✔
1821
                gfbio_abcd_data_provider_definition: None,
1✔
1822
                gfbio_collections_data_provider_definition: None,
1✔
1823
                ebv_portal_data_provider_definition: None,
1✔
1824
                net_cdf_cf_data_provider_definition: None,
1✔
1825
                pangaea_data_provider_definition: Some(data_provider_definition.clone()),
1✔
1826
            },
1✔
1827
        }
1828
    }
13✔
1829
}
1830

1831
impl TryFrom<TypedDataProviderDefinitionDbType> for TypedDataProviderDefinition {
1832
    type Error = Error;
1833

1834
    #[allow(clippy::too_many_lines)]
1835
    fn try_from(result_descriptor: TypedDataProviderDefinitionDbType) -> Result<Self, Self::Error> {
1836
        match result_descriptor {
9✔
1837
            TypedDataProviderDefinitionDbType {
1838
                aruna_data_provider_definition: Some(data_provider_definition),
1✔
1839
                gbif_data_provider_definition: None,
1✔
1840
                gfbio_abcd_data_provider_definition: None,
1✔
1841
                gfbio_collections_data_provider_definition: None,
1✔
1842
                ebv_portal_data_provider_definition: None,
1✔
1843
                net_cdf_cf_data_provider_definition: None,
1✔
1844
                pangaea_data_provider_definition: None,
1✔
1845
            } => Ok(TypedDataProviderDefinition::ArunaDataProviderDefinition(
1✔
1846
                data_provider_definition,
1✔
1847
            )),
1✔
1848
            TypedDataProviderDefinitionDbType {
1849
                aruna_data_provider_definition: None,
1850
                gbif_data_provider_definition: Some(data_provider_definition),
1✔
1851
                gfbio_abcd_data_provider_definition: None,
1✔
1852
                gfbio_collections_data_provider_definition: None,
1✔
1853
                ebv_portal_data_provider_definition: None,
1✔
1854
                net_cdf_cf_data_provider_definition: None,
1✔
1855
                pangaea_data_provider_definition: None,
1✔
1856
            } => Ok(TypedDataProviderDefinition::GbifDataProviderDefinition(
1✔
1857
                data_provider_definition,
1✔
1858
            )),
1✔
1859
            TypedDataProviderDefinitionDbType {
1860
                aruna_data_provider_definition: None,
1861
                gbif_data_provider_definition: None,
1862
                gfbio_abcd_data_provider_definition: Some(data_provider_definition),
1✔
1863
                gfbio_collections_data_provider_definition: None,
1✔
1864
                ebv_portal_data_provider_definition: None,
1✔
1865
                net_cdf_cf_data_provider_definition: None,
1✔
1866
                pangaea_data_provider_definition: None,
1✔
1867
            } => Ok(
1✔
1868
                TypedDataProviderDefinition::GfbioAbcdDataProviderDefinition(
1✔
1869
                    data_provider_definition,
1✔
1870
                ),
1✔
1871
            ),
1✔
1872
            TypedDataProviderDefinitionDbType {
1873
                aruna_data_provider_definition: None,
1874
                gbif_data_provider_definition: None,
1875
                gfbio_abcd_data_provider_definition: None,
1876
                gfbio_collections_data_provider_definition: Some(data_provider_definition),
1✔
1877
                ebv_portal_data_provider_definition: None,
1✔
1878
                net_cdf_cf_data_provider_definition: None,
1✔
1879
                pangaea_data_provider_definition: None,
1✔
1880
            } => Ok(
1✔
1881
                TypedDataProviderDefinition::GfbioCollectionsDataProviderDefinition(
1✔
1882
                    data_provider_definition,
1✔
1883
                ),
1✔
1884
            ),
1✔
1885
            TypedDataProviderDefinitionDbType {
1886
                aruna_data_provider_definition: None,
1887
                gbif_data_provider_definition: None,
1888
                gfbio_abcd_data_provider_definition: None,
1889
                gfbio_collections_data_provider_definition: None,
1890
                ebv_portal_data_provider_definition: Some(data_provider_definition),
2✔
1891
                net_cdf_cf_data_provider_definition: None,
2✔
1892
                pangaea_data_provider_definition: None,
2✔
1893
            } => Ok(
2✔
1894
                TypedDataProviderDefinition::EbvPortalDataProviderDefinition(
2✔
1895
                    data_provider_definition,
2✔
1896
                ),
2✔
1897
            ),
2✔
1898
            TypedDataProviderDefinitionDbType {
1899
                aruna_data_provider_definition: None,
1900
                gbif_data_provider_definition: None,
1901
                gfbio_abcd_data_provider_definition: None,
1902
                gfbio_collections_data_provider_definition: None,
1903
                ebv_portal_data_provider_definition: None,
1904
                net_cdf_cf_data_provider_definition: Some(data_provider_definition),
8✔
1905
                pangaea_data_provider_definition: None,
8✔
1906
            } => Ok(TypedDataProviderDefinition::NetCdfCfDataProviderDefinition(
8✔
1907
                data_provider_definition,
8✔
1908
            )),
8✔
1909
            TypedDataProviderDefinitionDbType {
1910
                aruna_data_provider_definition: None,
1911
                gbif_data_provider_definition: None,
1912
                gfbio_abcd_data_provider_definition: None,
1913
                gfbio_collections_data_provider_definition: None,
1914
                ebv_portal_data_provider_definition: None,
1915
                net_cdf_cf_data_provider_definition: None,
1916
                pangaea_data_provider_definition: Some(data_provider_definition),
1✔
1917
            } => Ok(TypedDataProviderDefinition::PangaeaDataProviderDefinition(
1✔
1918
                data_provider_definition,
1✔
1919
            )),
1✔
1920
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
1921
        }
1922
    }
15✔
1923
}
1924

1925
/// A macro for quickly implementing `FromSql` and `ToSql` for `$RustType` if there is a `From` and `Into`
1926
/// implementation for another type `$DbType` that already implements it.
1927
///
1928
/// # Usage
1929
///
1930
/// ```rust,ignore
1931
/// delegate_from_to_sql!($RustType, $DbType)
1932
/// ```
1933
///
1934
#[macro_export]
1935
macro_rules! delegate_from_to_sql {
1936
    ( $RustType:ty, $DbType:ty ) => {
1937
        impl ToSql for $RustType {
1938
            fn to_sql(
938✔
1939
                &self,
938✔
1940
                ty: &postgres_types::Type,
938✔
1941
                w: &mut bytes::BytesMut,
938✔
1942
            ) -> Result<postgres_types::IsNull, Box<dyn std::error::Error + Sync + Send>> {
938✔
1943
                <$DbType as ToSql>::to_sql(&self.into(), ty, w)
938✔
1944
            }
938✔
1945

1946
            fn accepts(ty: &postgres_types::Type) -> bool {
403✔
1947
                <$DbType as FromSql>::accepts(ty)
403✔
1948
            }
403✔
1949

1950
            postgres_types::to_sql_checked!();
1951
        }
1952

1953
        impl<'a> FromSql<'a> for $RustType {
1954
            fn from_sql(
509✔
1955
                ty: &postgres_types::Type,
509✔
1956
                raw: &'a [u8],
509✔
1957
            ) -> Result<$RustType, Box<dyn std::error::Error + Sync + Send>> {
509✔
1958
                Ok(<$DbType as FromSql>::from_sql(ty, raw)?.try_into()?)
509✔
1959
            }
509✔
1960

1961
            fn accepts(ty: &postgres_types::Type) -> bool {
10,801✔
1962
                <$DbType as FromSql>::accepts(ty)
10,801✔
1963
            }
10,801✔
1964
        }
1965
    };
1966
}
1967

1968
delegate_from_to_sql!(Colorizer, ColorizerDbType);
1969
delegate_from_to_sql!(ColorParam, ColorParamDbType);
1970
delegate_from_to_sql!(DatabaseConnectionConfig, DatabaseConnectionConfigDbType);
1971
delegate_from_to_sql!(DefaultColors, DefaultColorsDbType);
1972
delegate_from_to_sql!(
1973
    EbvPortalDataProviderDefinition,
1974
    EbvPortalDataProviderDefinitionDbType
1975
);
1976
delegate_from_to_sql!(FormatSpecifics, FormatSpecificsDbType);
1977
delegate_from_to_sql!(GdalDatasetParameters, GdalDatasetParametersDbType);
1978
delegate_from_to_sql!(GdalMetadataNetCdfCf, GdalMetadataNetCdfCfDbType);
1979
delegate_from_to_sql!(GdalMetaDataRegular, GdalMetaDataRegularDbType);
1980
delegate_from_to_sql!(
1981
    GfbioCollectionsDataProviderDefinition,
1982
    GfbioCollectionsDataProviderDefinitionDbType
1983
);
1984
delegate_from_to_sql!(Measurement, MeasurementDbType);
1985
delegate_from_to_sql!(MetaDataDefinition, MetaDataDefinitionDbType);
1986
delegate_from_to_sql!(MockMetaData, MockMetaDataDbType);
1987
delegate_from_to_sql!(NumberParam, NumberParamDbType);
1988
delegate_from_to_sql!(
1989
    NetCdfCfDataProviderDefinition,
1990
    NetCdfCfDataProviderDefinitionDbType
1991
);
1992
delegate_from_to_sql!(OgrMetaData, OgrMetaDataDbType);
1993
delegate_from_to_sql!(OgrSourceColumnSpec, OgrSourceColumnSpecDbType);
1994
delegate_from_to_sql!(OgrSourceDataset, OgrSourceDatasetDbType);
1995
delegate_from_to_sql!(OgrSourceDatasetTimeType, OgrSourceDatasetTimeTypeDbType);
1996
delegate_from_to_sql!(OgrSourceDurationSpec, OgrSourceDurationSpecDbType);
1997
delegate_from_to_sql!(OgrSourceTimeFormat, OgrSourceTimeFormatDbType);
1998
delegate_from_to_sql!(
1999
    PangaeaDataProviderDefinition,
2000
    PangaeaDataProviderDefinitionDbType
2001
);
2002
delegate_from_to_sql!(Symbology, SymbologyDbType);
2003
delegate_from_to_sql!(VectorResultDescriptor, VectorResultDescriptorDbType);
2004
delegate_from_to_sql!(
2005
    TypedDataProviderDefinition,
2006
    TypedDataProviderDefinitionDbType
2007
);
2008
delegate_from_to_sql!(TypedGeometry, TypedGeometryDbType);
2009
delegate_from_to_sql!(TypedResultDescriptor, TypedResultDescriptorDbType);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc