Skip to main content

rupg_common/
lib.rs

1//! `Error` with its `SqlState`, the identifiers `Oid`, `ShardId`, `RowId`, `Hlc`, `Xid` and `Lsn` of document 04 section 4.7, `CompatVersion`, and `qsort`, the sort of PostgreSQL.
2//!
3//! This crate first ships in milestone M1. See `spec/22-crate-layout.md` section 22.4 and `spec/23-milestones.md`.
4
5#![forbid(unsafe_code)]
6
7mod error;
8mod generated;
9mod ids;
10mod sort;
11mod sqlstate;
12
13pub use error::{Error, Level, Object, Result};
14pub use ids::{Hlc, Lsn, Oid, RowId, ShardId, Xid};
15pub use sort::qsort;
16pub use sqlstate::{Category, SqlState};
17
18use std::fmt;
19use std::str::FromStr;
20
21/// The PostgreSQL release that rupg follows. See `spec/05-compatibility.md`.
22pub const POSTGRES_PIN: &str = "19beta4";
23
24/// The commit of the PostgreSQL pin on `REL_19_STABLE`.
25pub const POSTGRES_COMMIT: &str = "7d3d2db7";
26
27/// A PostgreSQL major version that `rupg.compat_version` can name.
28///
29/// Version 19 is the native answer. Versions 14 to 18 are shims over the answer of version 19. See `spec/05-compatibility.md`.
30#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
31pub enum CompatVersion {
32    /// PostgreSQL 14.
33    V14,
34    /// PostgreSQL 15.
35    V15,
36    /// PostgreSQL 16.
37    V16,
38    /// PostgreSQL 17.
39    V17,
40    /// PostgreSQL 18.
41    V18,
42    /// PostgreSQL 19, the native version.
43    V19,
44}
45
46impl CompatVersion {
47    /// All versions, oldest first.
48    pub const ALL: [CompatVersion; 6] = [
49        CompatVersion::V14,
50        CompatVersion::V15,
51        CompatVersion::V16,
52        CompatVersion::V17,
53        CompatVersion::V18,
54        CompatVersion::V19,
55    ];
56
57    /// The native version. A shim maps the answer of this version to an older one.
58    pub const NATIVE: CompatVersion = CompatVersion::V19;
59
60    /// The major version number.
61    pub const fn major(self) -> u32 {
62        match self {
63            CompatVersion::V14 => 14,
64            CompatVersion::V15 => 15,
65            CompatVersion::V16 => 16,
66            CompatVersion::V17 => 17,
67            CompatVersion::V18 => 18,
68            CompatVersion::V19 => 19,
69        }
70    }
71
72    /// The value of `server_version_num` for this version. The shims report the minor release of the shim pin.
73    pub const fn server_version_num(self) -> u32 {
74        match self {
75            CompatVersion::V14 => 140024,
76            CompatVersion::V15 => 150019,
77            CompatVersion::V16 => 160015,
78            CompatVersion::V17 => 170011,
79            CompatVersion::V18 => 180006,
80            CompatVersion::V19 => 190000,
81        }
82    }
83}
84
85impl fmt::Display for CompatVersion {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        write!(f, "{}", self.major())
88    }
89}
90
91/// The error when a string does not name a supported version.
92#[derive(Clone, Debug, PartialEq, Eq)]
93pub struct UnknownVersion(pub String);
94
95impl fmt::Display for UnknownVersion {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        write!(f, "unknown PostgreSQL version {:?}, expected 14 to 19", self.0)
98    }
99}
100
101impl std::error::Error for UnknownVersion {}
102
103impl FromStr for CompatVersion {
104    type Err = UnknownVersion;
105
106    fn from_str(s: &str) -> Result<Self, Self::Err> {
107        CompatVersion::ALL
108            .into_iter()
109            .find(|v| v.major().to_string() == s.trim())
110            .ok_or_else(|| UnknownVersion(s.to_string()))
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use super::*;
117
118    #[test]
119    fn parse_every_version() {
120        for v in CompatVersion::ALL {
121            assert_eq!(v.to_string().parse::<CompatVersion>(), Ok(v));
122        }
123    }
124
125    #[test]
126    fn reject_unknown_versions() {
127        assert!("13".parse::<CompatVersion>().is_err());
128        assert!("20".parse::<CompatVersion>().is_err());
129        assert!("".parse::<CompatVersion>().is_err());
130    }
131
132    #[test]
133    fn version_numbers_match_the_major() {
134        for v in CompatVersion::ALL {
135            assert_eq!(v.server_version_num() / 10000, v.major());
136        }
137    }
138}