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

geo-engine / geoengine / 12864321835

20 Jan 2025 08:53AM UTC coverage: 90.007% (-0.6%) from 90.64%
12864321835

Pull #1008

github

web-flow
Merge c723a3956 into de81b44f7
Pull Request #1008: user ctx in ge_test

3447 of 3549 new or added lines in 64 files covered. (97.13%)

785 existing lines in 18 files now uncovered.

127380 of 141522 relevant lines covered (90.01%)

56878.89 hits per line

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

93.83
/services/src/util/postgres.rs
1
use bb8_postgres::{bb8::PooledConnection, PostgresConnectionManager};
2
use serde::{Deserialize, Serialize};
3
use tokio_postgres::Config;
4

5
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
6
pub struct DatabaseConnectionConfig {
7
    pub host: String,
8
    pub port: u16,
9
    pub database: String,
10
    pub schema: String,
11
    pub user: String,
12
    pub password: String,
13
}
14

15
impl DatabaseConnectionConfig {
16
    pub fn pg_config(&self) -> Config {
976✔
17
        let mut config = Config::new();
976✔
18
        config
976✔
19
            .user(&self.user)
976✔
20
            .password(&self.password)
976✔
21
            .host(&self.host)
976✔
22
            .dbname(&self.database)
976✔
23
            .port(self.port)
976✔
24
            .options(format!("-c search_path={}", self.schema));
976✔
25
        config
976✔
26
    }
976✔
27

28
    pub fn ogr_pg_config(&self) -> String {
16✔
29
        format!(
16✔
30
            "PG:host={} port={} dbname={} user={} password={}",
16✔
31
            self.host, self.port, self.database, self.user, self.password
16✔
32
        )
16✔
33
    }
16✔
34
}
35

36
impl From<crate::config::Postgres> for DatabaseConnectionConfig {
37
    fn from(config: crate::config::Postgres) -> Self {
24✔
38
        Self {
24✔
39
            host: config.host,
24✔
40
            port: config.port,
24✔
41
            database: config.database,
24✔
42
            schema: config.schema,
24✔
43
            user: config.user,
24✔
44
            password: config.password,
24✔
45
        }
24✔
46
    }
24✔
47
}
48

49
/// test `FromSql`/`ToSql` for a type and its postgres type
50
///
51
/// # Panics
52
///
53
/// Panics if the type cannot be converted to/from postgres
54
///
55
pub async fn assert_sql_type<T>(
7✔
56
    conn: &PooledConnection<'_, PostgresConnectionManager<tokio_postgres::NoTls>>,
7✔
57
    sql_type: &str,
7✔
58
    checks: impl IntoIterator<Item = T>,
7✔
59
) where
7✔
60
    T: PartialEq + postgres_types::FromSqlOwned + postgres_types::ToSql + Sync,
7✔
61
{
7✔
62
    const UNQUOTED: [&str; 3] = ["double precision", "int", "point[]"];
63

64
    // don't quote built-in types
65
    let quote = if UNQUOTED.contains(&sql_type) || sql_type.contains('[') {
7✔
UNCOV
66
        ""
×
67
    } else {
68
        "\""
7✔
69
    };
70

71
    for value in checks {
15✔
72
        let stmt = conn
8✔
73
            .prepare(&format!("SELECT $1::{quote}{sql_type}{quote}"))
8✔
74
            .await
8✔
75
            .expect("it should panic since this is an assertion");
8✔
76
        let result: T = conn
8✔
77
            .query_one(&stmt, &[&value])
8✔
78
            .await
8✔
79
            .expect("it should panic since this is an assertion")
8✔
80
            .get(0);
8✔
81

8✔
82
        assert_eq!(value, result);
8✔
83
    }
84
}
7✔
85

86
/// Checks whether the given error presents a unique constraint violation on the given column
87
pub fn postgres_error_is_unique_violation(
15✔
88
    err: &tokio_postgres::Error,
15✔
89
    table_name: &str,
15✔
90
    column_name: &str,
15✔
91
) -> bool {
15✔
92
    if err.code() != Some(&tokio_postgres::error::SqlState::UNIQUE_VIOLATION) {
15✔
93
        return false;
×
94
    }
15✔
95

96
    let Some(db_error) = err.as_db_error() else {
15✔
97
        return false;
×
98
    };
99

100
    let Some(constraint) = db_error.constraint() else {
15✔
101
        return false;
×
102
    };
103

104
    let expected_constraint_name = format!("{table_name}_{column_name}_key");
15✔
105

15✔
106
    constraint == expected_constraint_name
15✔
107
}
15✔
108

109
pub trait PostgresErrorExt<T, E> {
110
    /// Maps a postgres unique violation that matches a specific table and column to a custom error.
111
    /// Otherwise it returns the original error.
112
    fn map_unique_violation(
113
        self,
114
        table_name: &str,
115
        column_name: &str,
116
        map_unique_violation: impl FnOnce() -> E,
117
    ) -> Result<T, E>;
118
}
119

120
impl<T, E> PostgresErrorExt<T, E> for Result<T, tokio_postgres::Error>
121
where
122
    E: From<tokio_postgres::Error>,
123
{
124
    fn map_unique_violation(
143✔
125
        self,
143✔
126
        table_name: &str,
143✔
127
        column_name: &str,
143✔
128
        map_unique_violation: impl FnOnce() -> E,
143✔
129
    ) -> Result<T, E> {
143✔
130
        let postgres_error = match self {
143✔
131
            Ok(v) => return Ok(v),
128✔
132
            Err(e) => e,
15✔
133
        };
15✔
134

15✔
135
        if postgres_error_is_unique_violation(&postgres_error, table_name, column_name) {
15✔
136
            Err(map_unique_violation())
15✔
137
        } else {
138
            Err(postgres_error.into())
×
139
        }
140
    }
143✔
141
}
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