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

geo-engine / geoengine / 6147514757

11 Sep 2023 02:05PM UTC coverage: 89.892% (-0.09%) from 89.985%
6147514757

Pull #873

github

web-flow
Merge 3a80eaf16 into 664a57cd7
Pull Request #873: Edr provider (TEST)

1389 of 1389 new or added lines in 3 files covered. (100.0%)

107997 of 120141 relevant lines covered (89.89%)

60267.52 hits per line

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

93.02
/services/src/api/model/db_types.rs
1
use super::{
2
    datatypes::{
3
        BoundingBox2D, Breakpoint, ClassificationMeasurement, Colorizer, ContinuousMeasurement,
4
        Coordinate2D, DataProviderId, DateTimeParseFormat, DefaultColors, FeatureDataType,
5
        LinearGradient, LogarithmicGradient, Measurement, MultiLineString, MultiPoint,
6
        MultiPolygon, NoGeometry, OverUnderColors, Palette, RgbaColor, SpatialReferenceOption,
7
        TimeInstance, TimeInterval, 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
            edr::{EdrDataProviderDefinition, EdrVectorSpec},
24
            gbif::GbifDataProviderDefinition,
25
            gfbio_abcd::GfbioAbcdDataProviderDefinition,
26
            gfbio_collections::GfbioCollectionsDataProviderDefinition,
27
            netcdfcf::{EbvPortalDataProviderDefinition, NetCdfCfDataProviderDefinition},
28
            pangaea::PangaeaDataProviderDefinition,
29
        },
30
        listing::Provenance,
31
        storage::MetaDataDefinition,
32
    },
33
    error::Error,
34
    layers::external::TypedDataProviderDefinition,
35
    projects::{
36
        ColorParam, DerivedColor, DerivedNumber, LineSymbology, NumberParam, PointSymbology,
37
        PolygonSymbology, RasterSymbology, Symbology,
38
    },
39
    util::postgres::DatabaseConnectionConfig,
40
};
41
use fallible_iterator::FallibleIterator;
42
use geoengine_datatypes::primitives::CacheTtlSeconds;
43
use ordered_float::NotNan;
44
use postgres_types::{FromSql, ToSql};
45
use std::{collections::HashMap, marker::PhantomData};
46

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

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

72
impl TryFrom<DefaultColorsDbType> for DefaultColors {
73
    type Error = Error;
74

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

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

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

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

155
impl TryFrom<ColorizerDbType> for Colorizer {
156
    type Error = Error;
157

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

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

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

238
impl TryFrom<ColorParamDbType> for ColorParam {
239
    type Error = Error;
240

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

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

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

295
impl TryFrom<NumberParamDbType> for NumberParam {
296
    type Error = Error;
297

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

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

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

363
impl TryFrom<SymbologyDbType> for Symbology {
364
    type Error = Error;
365

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

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

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

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

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

446
impl TryFrom<MeasurementDbType> for Measurement {
447
    type Error = Error;
448

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

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

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

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

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

519
impl TryFrom<VectorResultDescriptorDbType> for VectorResultDescriptor {
520
    type Error = Error;
521

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

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

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

575
impl TryFrom<TypedResultDescriptorDbType> for TypedResultDescriptor {
576
    type Error = Error;
577

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

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

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

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

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

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

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

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

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

681
impl TryFrom<OgrSourceTimeFormatDbType> for OgrSourceTimeFormat {
682
    type Error = Error;
683

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

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

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

738
impl TryFrom<OgrSourceDurationSpecDbType> for OgrSourceDurationSpec {
739
    type Error = Error;
740

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

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

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

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

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

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

849
impl TryFrom<OgrSourceDatasetTimeTypeDbType> for OgrSourceDatasetTimeType {
850
    type Error = Error;
851

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

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

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

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

914
impl TryFrom<FormatSpecificsDbType> for FormatSpecifics {
915
    type Error = Error;
916

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

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

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

957
impl TryFrom<OgrSourceColumnSpecDbType> for OgrSourceColumnSpec {
958
    type Error = Error;
959

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

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

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

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

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

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

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

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

1020
        Ok(postgres_types::IsNull::No)
4✔
1021
    }
4✔
1022

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

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

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

1036
        matches!(inner_type, &postgres_types::Type::PATH)
1✔
1037
    }
1✔
1038

1039
    postgres_types::to_sql_checked!();
1040
}
1041

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

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

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

1073
        Ok(Self { rings })
4✔
1074
    }
4✔
1075

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

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

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

1089
        matches!(inner_type, &postgres_types::Type::PATH)
×
1090
    }
×
1091
}
1092

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

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

1133
impl TryFrom<TypedGeometryDbType> for TypedGeometry {
1134
    type Error = Error;
1135

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

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

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

1203
impl TryFrom<OgrSourceDatasetDbType> for OgrSourceDataset {
1204
    type Error = Error;
1205

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

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

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

1240
impl TryFrom<OgrMetaDataDbType> for OgrMetaData {
1241
    type Error = Error;
1242

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

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

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

1268
impl TryFrom<MockMetaDataDbType> for MockMetaData {
1269
    type Error = Error;
1270

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

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

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

1314
impl TryFrom<GdalDatasetParametersDbType> for GdalDatasetParameters {
1315
    type Error = Error;
1316

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

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

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

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

1371
impl TryFrom<GdalMetaDataRegularDbType> for GdalMetaDataRegular {
1372
    type Error = Error;
1373

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

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

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

1416
impl TryFrom<GdalMetadataNetCdfCfDbType> for GdalMetadataNetCdfCf {
1417
    type Error = Error;
1418

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

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

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

1498
impl TryFrom<MetaDataDefinitionDbType> for MetaDataDefinition {
1499
    type Error = Error;
1500

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

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

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

1580
impl TryFrom<DatabaseConnectionConfigDbType> for DatabaseConnectionConfig {
1581
    type Error = Error;
1582

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

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

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

1621
impl TryFrom<GfbioCollectionsDataProviderDefinitionDbType>
1622
    for GfbioCollectionsDataProviderDefinition
1623
{
1624
    type Error = Error;
1625

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

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

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

1660
impl TryFrom<EbvPortalDataProviderDefinitionDbType> for EbvPortalDataProviderDefinition {
1661
    type Error = Error;
1662

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

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

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

1694
impl TryFrom<NetCdfCfDataProviderDefinitionDbType> for NetCdfCfDataProviderDefinition {
1695
    type Error = Error;
1696

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

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

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

1725
impl TryFrom<PangaeaDataProviderDefinitionDbType> for PangaeaDataProviderDefinition {
1726
    type Error = Error;
1727

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

1737
#[derive(Debug, ToSql, FromSql)]
116✔
1738
#[postgres(name = "EdrVectorSpec")]
1739
pub struct EdrVectorSpecDbType {
1740
    x: String,
1741
    y: Option<String>,
1742
    time: String,
1743
}
1744

1745
impl From<&EdrVectorSpec> for EdrVectorSpecDbType {
1746
    fn from(other: &EdrVectorSpec) -> Self {
×
1747
        Self {
×
1748
            x: other.x.clone(),
×
1749
            y: other.y.clone(),
×
1750
            time: other.time.clone(),
×
1751
        }
×
1752
    }
×
1753
}
1754

1755
impl TryFrom<EdrVectorSpecDbType> for EdrVectorSpec {
1756
    type Error = Error;
1757

1758
    fn try_from(other: EdrVectorSpecDbType) -> Result<Self, Self::Error> {
×
1759
        Ok(Self {
×
1760
            x: other.x,
×
1761
            y: other.y,
×
1762
            time: other.time,
×
1763
        })
×
1764
    }
×
1765
}
1766

1767
#[derive(Debug, ToSql, FromSql)]
232✔
1768
#[postgres(name = "EdrDataProviderDefinition")]
1769
pub struct EdrDataProviderDefinitionDbType {
1770
    name: String,
1771
    id: DataProviderId,
1772
    base_url: String,
1773
    vector_spec: Option<EdrVectorSpec>,
1774
    cache_ttl: CacheTtlSeconds,
1775
    /// List of vertical reference systems with a discrete scale
1776
    discrete_vrs: Vec<String>,
1777
    provenance: Option<Vec<Provenance>>,
1778
}
1779

1780
impl From<&EdrDataProviderDefinition> for EdrDataProviderDefinitionDbType {
1781
    fn from(other: &EdrDataProviderDefinition) -> Self {
×
1782
        Self {
×
1783
            name: other.name.clone(),
×
1784
            id: other.id,
×
1785
            base_url: other.base_url.clone().into(),
×
1786
            vector_spec: other.vector_spec.clone(),
×
1787
            cache_ttl: other.cache_ttl,
×
1788
            discrete_vrs: other.discrete_vrs.clone(),
×
1789
            provenance: other.provenance.clone(),
×
1790
        }
×
1791
    }
×
1792
}
1793

1794
impl TryFrom<EdrDataProviderDefinitionDbType> for EdrDataProviderDefinition {
1795
    type Error = Error;
1796

1797
    fn try_from(other: EdrDataProviderDefinitionDbType) -> Result<Self, Self::Error> {
×
1798
        Ok(Self {
×
1799
            name: other.name,
×
1800
            id: other.id,
×
1801
            base_url: other.base_url.as_str().try_into()?,
×
1802
            vector_spec: other.vector_spec,
×
1803
            cache_ttl: other.cache_ttl,
×
1804
            discrete_vrs: other.discrete_vrs,
×
1805
            provenance: other.provenance,
×
1806
        })
1807
    }
×
1808
}
1809

1810
#[derive(Debug, ToSql, FromSql)]
261✔
1811
#[postgres(name = "DataProviderDefinition")]
1812
pub struct TypedDataProviderDefinitionDbType {
1813
    aruna_data_provider_definition: Option<ArunaDataProviderDefinition>,
1814
    gbif_data_provider_definition: Option<GbifDataProviderDefinition>,
1815
    gfbio_abcd_data_provider_definition: Option<GfbioAbcdDataProviderDefinition>,
1816
    gfbio_collections_data_provider_definition: Option<GfbioCollectionsDataProviderDefinition>,
1817
    ebv_portal_data_provider_definition: Option<EbvPortalDataProviderDefinition>,
1818
    net_cdf_cf_data_provider_definition: Option<NetCdfCfDataProviderDefinition>,
1819
    pangaea_data_provider_definition: Option<PangaeaDataProviderDefinition>,
1820
    edr_data_provider_definition: Option<EdrDataProviderDefinition>,
1821
}
1822

1823
impl From<&TypedDataProviderDefinition> for TypedDataProviderDefinitionDbType {
1824
    fn from(other: &TypedDataProviderDefinition) -> Self {
13✔
1825
        match other {
13✔
1826
            TypedDataProviderDefinition::ArunaDataProviderDefinition(data_provider_definition) => {
1✔
1827
                Self {
1✔
1828
                    aruna_data_provider_definition: Some(data_provider_definition.clone()),
1✔
1829
                    gbif_data_provider_definition: None,
1✔
1830
                    gfbio_abcd_data_provider_definition: None,
1✔
1831
                    gfbio_collections_data_provider_definition: None,
1✔
1832
                    ebv_portal_data_provider_definition: None,
1✔
1833
                    net_cdf_cf_data_provider_definition: None,
1✔
1834
                    pangaea_data_provider_definition: None,
1✔
1835
                    edr_data_provider_definition: None,
1✔
1836
                }
1✔
1837
            }
1838
            TypedDataProviderDefinition::GbifDataProviderDefinition(data_provider_definition) => {
1✔
1839
                Self {
1✔
1840
                    aruna_data_provider_definition: None,
1✔
1841
                    gbif_data_provider_definition: Some(data_provider_definition.clone()),
1✔
1842
                    gfbio_abcd_data_provider_definition: None,
1✔
1843
                    gfbio_collections_data_provider_definition: None,
1✔
1844
                    ebv_portal_data_provider_definition: None,
1✔
1845
                    net_cdf_cf_data_provider_definition: None,
1✔
1846
                    pangaea_data_provider_definition: None,
1✔
1847
                    edr_data_provider_definition: None,
1✔
1848
                }
1✔
1849
            }
1850
            TypedDataProviderDefinition::GfbioAbcdDataProviderDefinition(
1851
                data_provider_definition,
1✔
1852
            ) => Self {
1✔
1853
                aruna_data_provider_definition: None,
1✔
1854
                gbif_data_provider_definition: None,
1✔
1855
                gfbio_abcd_data_provider_definition: Some(data_provider_definition.clone()),
1✔
1856
                gfbio_collections_data_provider_definition: None,
1✔
1857
                ebv_portal_data_provider_definition: None,
1✔
1858
                net_cdf_cf_data_provider_definition: None,
1✔
1859
                pangaea_data_provider_definition: None,
1✔
1860
                edr_data_provider_definition: None,
1✔
1861
            },
1✔
1862
            TypedDataProviderDefinition::GfbioCollectionsDataProviderDefinition(
1863
                data_provider_definition,
1✔
1864
            ) => Self {
1✔
1865
                aruna_data_provider_definition: None,
1✔
1866
                gbif_data_provider_definition: None,
1✔
1867
                gfbio_abcd_data_provider_definition: None,
1✔
1868
                gfbio_collections_data_provider_definition: Some(data_provider_definition.clone()),
1✔
1869
                ebv_portal_data_provider_definition: None,
1✔
1870
                net_cdf_cf_data_provider_definition: None,
1✔
1871
                pangaea_data_provider_definition: None,
1✔
1872
                edr_data_provider_definition: None,
1✔
1873
            },
1✔
1874
            TypedDataProviderDefinition::EbvPortalDataProviderDefinition(
1875
                data_provider_definition,
2✔
1876
            ) => Self {
2✔
1877
                aruna_data_provider_definition: None,
2✔
1878
                gbif_data_provider_definition: None,
2✔
1879
                gfbio_abcd_data_provider_definition: None,
2✔
1880
                gfbio_collections_data_provider_definition: None,
2✔
1881
                ebv_portal_data_provider_definition: Some(data_provider_definition.clone()),
2✔
1882
                net_cdf_cf_data_provider_definition: None,
2✔
1883
                pangaea_data_provider_definition: None,
2✔
1884
                edr_data_provider_definition: None,
2✔
1885
            },
2✔
1886
            TypedDataProviderDefinition::NetCdfCfDataProviderDefinition(
1887
                data_provider_definition,
6✔
1888
            ) => Self {
6✔
1889
                aruna_data_provider_definition: None,
6✔
1890
                gbif_data_provider_definition: None,
6✔
1891
                gfbio_abcd_data_provider_definition: None,
6✔
1892
                gfbio_collections_data_provider_definition: None,
6✔
1893
                ebv_portal_data_provider_definition: None,
6✔
1894
                net_cdf_cf_data_provider_definition: Some(data_provider_definition.clone()),
6✔
1895
                pangaea_data_provider_definition: None,
6✔
1896
                edr_data_provider_definition: None,
6✔
1897
            },
6✔
1898
            TypedDataProviderDefinition::PangaeaDataProviderDefinition(
1899
                data_provider_definition,
1✔
1900
            ) => Self {
1✔
1901
                aruna_data_provider_definition: None,
1✔
1902
                gbif_data_provider_definition: None,
1✔
1903
                gfbio_abcd_data_provider_definition: None,
1✔
1904
                gfbio_collections_data_provider_definition: None,
1✔
1905
                ebv_portal_data_provider_definition: None,
1✔
1906
                net_cdf_cf_data_provider_definition: None,
1✔
1907
                pangaea_data_provider_definition: Some(data_provider_definition.clone()),
1✔
1908
                edr_data_provider_definition: None,
1✔
1909
            },
1✔
1910
            TypedDataProviderDefinition::EdrDataProviderDefinition(data_provider_definition) => {
×
1911
                Self {
×
1912
                    aruna_data_provider_definition: None,
×
1913
                    gbif_data_provider_definition: None,
×
1914
                    gfbio_abcd_data_provider_definition: None,
×
1915
                    gfbio_collections_data_provider_definition: None,
×
1916
                    ebv_portal_data_provider_definition: None,
×
1917
                    net_cdf_cf_data_provider_definition: None,
×
1918
                    pangaea_data_provider_definition: None,
×
1919
                    edr_data_provider_definition: Some(data_provider_definition.clone()),
×
1920
                }
×
1921
            }
1922
        }
1923
    }
13✔
1924
}
1925

1926
impl TryFrom<TypedDataProviderDefinitionDbType> for TypedDataProviderDefinition {
1927
    type Error = Error;
1928

1929
    #[allow(clippy::too_many_lines)]
1930
    fn try_from(result_descriptor: TypedDataProviderDefinitionDbType) -> Result<Self, Self::Error> {
1931
        match result_descriptor {
1✔
1932
            TypedDataProviderDefinitionDbType {
1933
                aruna_data_provider_definition: Some(data_provider_definition),
1✔
1934
                gbif_data_provider_definition: None,
1✔
1935
                gfbio_abcd_data_provider_definition: None,
1✔
1936
                gfbio_collections_data_provider_definition: None,
1✔
1937
                ebv_portal_data_provider_definition: None,
1✔
1938
                net_cdf_cf_data_provider_definition: None,
1✔
1939
                pangaea_data_provider_definition: None,
1✔
1940
                edr_data_provider_definition: None,
1✔
1941
            } => Ok(TypedDataProviderDefinition::ArunaDataProviderDefinition(
1✔
1942
                data_provider_definition,
1✔
1943
            )),
1✔
1944
            TypedDataProviderDefinitionDbType {
1945
                aruna_data_provider_definition: None,
1946
                gbif_data_provider_definition: Some(data_provider_definition),
1✔
1947
                gfbio_abcd_data_provider_definition: None,
1✔
1948
                gfbio_collections_data_provider_definition: None,
1✔
1949
                ebv_portal_data_provider_definition: None,
1✔
1950
                net_cdf_cf_data_provider_definition: None,
1✔
1951
                pangaea_data_provider_definition: None,
1✔
1952
                edr_data_provider_definition: None,
1✔
1953
            } => Ok(TypedDataProviderDefinition::GbifDataProviderDefinition(
1✔
1954
                data_provider_definition,
1✔
1955
            )),
1✔
1956
            TypedDataProviderDefinitionDbType {
1957
                aruna_data_provider_definition: None,
1958
                gbif_data_provider_definition: None,
1959
                gfbio_abcd_data_provider_definition: Some(data_provider_definition),
1✔
1960
                gfbio_collections_data_provider_definition: None,
1✔
1961
                ebv_portal_data_provider_definition: None,
1✔
1962
                net_cdf_cf_data_provider_definition: None,
1✔
1963
                pangaea_data_provider_definition: None,
1✔
1964
                edr_data_provider_definition: None,
1✔
1965
            } => Ok(
1✔
1966
                TypedDataProviderDefinition::GfbioAbcdDataProviderDefinition(
1✔
1967
                    data_provider_definition,
1✔
1968
                ),
1✔
1969
            ),
1✔
1970
            TypedDataProviderDefinitionDbType {
1971
                aruna_data_provider_definition: None,
1972
                gbif_data_provider_definition: None,
1973
                gfbio_abcd_data_provider_definition: None,
1974
                gfbio_collections_data_provider_definition: Some(data_provider_definition),
1✔
1975
                ebv_portal_data_provider_definition: None,
1✔
1976
                net_cdf_cf_data_provider_definition: None,
1✔
1977
                pangaea_data_provider_definition: None,
1✔
1978
                edr_data_provider_definition: None,
1✔
1979
            } => Ok(
1✔
1980
                TypedDataProviderDefinition::GfbioCollectionsDataProviderDefinition(
1✔
1981
                    data_provider_definition,
1✔
1982
                ),
1✔
1983
            ),
1✔
1984
            TypedDataProviderDefinitionDbType {
1985
                aruna_data_provider_definition: None,
1986
                gbif_data_provider_definition: None,
1987
                gfbio_abcd_data_provider_definition: None,
1988
                gfbio_collections_data_provider_definition: None,
1989
                ebv_portal_data_provider_definition: Some(data_provider_definition),
2✔
1990
                net_cdf_cf_data_provider_definition: None,
2✔
1991
                pangaea_data_provider_definition: None,
2✔
1992
                edr_data_provider_definition: None,
2✔
1993
            } => Ok(
2✔
1994
                TypedDataProviderDefinition::EbvPortalDataProviderDefinition(
2✔
1995
                    data_provider_definition,
2✔
1996
                ),
2✔
1997
            ),
2✔
1998
            TypedDataProviderDefinitionDbType {
1999
                aruna_data_provider_definition: None,
2000
                gbif_data_provider_definition: None,
2001
                gfbio_abcd_data_provider_definition: None,
2002
                gfbio_collections_data_provider_definition: None,
2003
                ebv_portal_data_provider_definition: None,
2004
                net_cdf_cf_data_provider_definition: Some(data_provider_definition),
8✔
2005
                pangaea_data_provider_definition: None,
8✔
2006
                edr_data_provider_definition: None,
8✔
2007
            } => Ok(TypedDataProviderDefinition::NetCdfCfDataProviderDefinition(
8✔
2008
                data_provider_definition,
8✔
2009
            )),
8✔
2010
            TypedDataProviderDefinitionDbType {
2011
                aruna_data_provider_definition: None,
2012
                gbif_data_provider_definition: None,
2013
                gfbio_abcd_data_provider_definition: None,
2014
                gfbio_collections_data_provider_definition: None,
2015
                ebv_portal_data_provider_definition: None,
2016
                net_cdf_cf_data_provider_definition: None,
2017
                pangaea_data_provider_definition: Some(data_provider_definition),
1✔
2018
                edr_data_provider_definition: None,
1✔
2019
            } => Ok(TypedDataProviderDefinition::PangaeaDataProviderDefinition(
1✔
2020
                data_provider_definition,
1✔
2021
            )),
1✔
2022
            TypedDataProviderDefinitionDbType {
2023
                aruna_data_provider_definition: None,
2024
                gbif_data_provider_definition: None,
2025
                gfbio_abcd_data_provider_definition: None,
2026
                gfbio_collections_data_provider_definition: None,
2027
                ebv_portal_data_provider_definition: None,
2028
                net_cdf_cf_data_provider_definition: None,
2029
                pangaea_data_provider_definition: None,
2030
                edr_data_provider_definition: Some(data_provider_definition),
×
2031
            } => Ok(TypedDataProviderDefinition::EdrDataProviderDefinition(
×
2032
                data_provider_definition,
×
2033
            )),
×
2034
            _ => Err(Error::UnexpectedInvalidDbTypeConversion),
×
2035
        }
2036
    }
15✔
2037
}
2038

2039
/// A macro for quickly implementing `FromSql` and `ToSql` for `$RustType` if there is a `From` and `Into`
2040
/// implementation for another type `$DbType` that already implements it.
2041
///
2042
/// # Usage
2043
///
2044
/// ```rust,ignore
2045
/// delegate_from_to_sql!($RustType, $DbType)
2046
/// ```
2047
///
2048
#[macro_export]
2049
macro_rules! delegate_from_to_sql {
2050
    ( $RustType:ty, $DbType:ty ) => {
2051
        impl ToSql for $RustType {
2052
            fn to_sql(
938✔
2053
                &self,
938✔
2054
                ty: &postgres_types::Type,
938✔
2055
                w: &mut bytes::BytesMut,
938✔
2056
            ) -> Result<postgres_types::IsNull, Box<dyn std::error::Error + Sync + Send>> {
938✔
2057
                <$DbType as ToSql>::to_sql(&self.into(), ty, w)
938✔
2058
            }
938✔
2059

2060
            fn accepts(ty: &postgres_types::Type) -> bool {
403✔
2061
                <$DbType as FromSql>::accepts(ty)
403✔
2062
            }
403✔
2063

2064
            postgres_types::to_sql_checked!();
2065
        }
2066

2067
        impl<'a> FromSql<'a> for $RustType {
2068
            fn from_sql(
509✔
2069
                ty: &postgres_types::Type,
509✔
2070
                raw: &'a [u8],
509✔
2071
            ) -> Result<$RustType, Box<dyn std::error::Error + Sync + Send>> {
509✔
2072
                Ok(<$DbType as FromSql>::from_sql(ty, raw)?.try_into()?)
509✔
2073
            }
509✔
2074

2075
            fn accepts(ty: &postgres_types::Type) -> bool {
10,859✔
2076
                <$DbType as FromSql>::accepts(ty)
10,859✔
2077
            }
10,859✔
2078
        }
2079
    };
2080
}
2081

2082
delegate_from_to_sql!(Colorizer, ColorizerDbType);
2083
delegate_from_to_sql!(ColorParam, ColorParamDbType);
2084
delegate_from_to_sql!(DatabaseConnectionConfig, DatabaseConnectionConfigDbType);
2085
delegate_from_to_sql!(DefaultColors, DefaultColorsDbType);
2086
delegate_from_to_sql!(
2087
    EbvPortalDataProviderDefinition,
2088
    EbvPortalDataProviderDefinitionDbType
2089
);
2090
delegate_from_to_sql!(FormatSpecifics, FormatSpecificsDbType);
2091
delegate_from_to_sql!(GdalDatasetParameters, GdalDatasetParametersDbType);
2092
delegate_from_to_sql!(GdalMetadataNetCdfCf, GdalMetadataNetCdfCfDbType);
2093
delegate_from_to_sql!(GdalMetaDataRegular, GdalMetaDataRegularDbType);
2094
delegate_from_to_sql!(
2095
    GfbioCollectionsDataProviderDefinition,
2096
    GfbioCollectionsDataProviderDefinitionDbType
2097
);
2098
delegate_from_to_sql!(Measurement, MeasurementDbType);
2099
delegate_from_to_sql!(MetaDataDefinition, MetaDataDefinitionDbType);
2100
delegate_from_to_sql!(MockMetaData, MockMetaDataDbType);
2101
delegate_from_to_sql!(NumberParam, NumberParamDbType);
2102
delegate_from_to_sql!(
2103
    NetCdfCfDataProviderDefinition,
2104
    NetCdfCfDataProviderDefinitionDbType
2105
);
2106
delegate_from_to_sql!(OgrMetaData, OgrMetaDataDbType);
2107
delegate_from_to_sql!(OgrSourceColumnSpec, OgrSourceColumnSpecDbType);
2108
delegate_from_to_sql!(OgrSourceDataset, OgrSourceDatasetDbType);
2109
delegate_from_to_sql!(OgrSourceDatasetTimeType, OgrSourceDatasetTimeTypeDbType);
2110
delegate_from_to_sql!(OgrSourceDurationSpec, OgrSourceDurationSpecDbType);
2111
delegate_from_to_sql!(OgrSourceTimeFormat, OgrSourceTimeFormatDbType);
2112
delegate_from_to_sql!(
2113
    PangaeaDataProviderDefinition,
2114
    PangaeaDataProviderDefinitionDbType
2115
);
2116
delegate_from_to_sql!(EdrDataProviderDefinition, EdrDataProviderDefinitionDbType);
2117
delegate_from_to_sql!(EdrVectorSpec, EdrVectorSpecDbType);
2118
delegate_from_to_sql!(Symbology, SymbologyDbType);
2119
delegate_from_to_sql!(VectorResultDescriptor, VectorResultDescriptorDbType);
2120
delegate_from_to_sql!(
2121
    TypedDataProviderDefinition,
2122
    TypedDataProviderDefinitionDbType
2123
);
2124
delegate_from_to_sql!(TypedGeometry, TypedGeometryDbType);
2125
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