pgevolve_core/catalog/
version.rs1use crate::catalog::error::CatalogError;
4use crate::catalog::{CatalogQuerier, CatalogQuery};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum PgVersion {
9 Pg14,
11 Pg15,
13 Pg16,
15 Pg17,
17 Pg18,
19}
20
21impl PgVersion {
22 pub fn detect(querier: &dyn CatalogQuerier) -> Result<Self, CatalogError> {
24 let rows = querier.fetch(CatalogQuery::PgVersion, &[])?;
25 let row = rows.into_iter().next().ok_or(CatalogError::MissingResult {
26 query: CatalogQuery::PgVersion,
27 })?;
28 let n = row.get_int(CatalogQuery::PgVersion, "server_version_num")?;
29 Self::from_server_version_num(n)
30 }
31
32 pub fn from_server_version_num(n: i64) -> Result<Self, CatalogError> {
36 let major = n / 10_000;
37 match major {
38 14 => Ok(Self::Pg14),
39 15 => Ok(Self::Pg15),
40 16 => Ok(Self::Pg16),
41 17 => Ok(Self::Pg17),
42 18 => Ok(Self::Pg18),
43 v => Err(CatalogError::UnsupportedPgVersion(
44 v.try_into().unwrap_or(0),
45 )),
46 }
47 }
48
49 #[must_use]
51 pub const fn as_tag(self) -> &'static str {
52 match self {
53 Self::Pg14 => "pg14",
54 Self::Pg15 => "pg15",
55 Self::Pg16 => "pg16",
56 Self::Pg17 => "pg17",
57 Self::Pg18 => "pg18",
58 }
59 }
60
61 #[must_use]
63 pub const fn major(self) -> u32 {
64 match self {
65 Self::Pg14 => 14,
66 Self::Pg15 => 15,
67 Self::Pg16 => 16,
68 Self::Pg17 => 17,
69 Self::Pg18 => 18,
70 }
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use crate::catalog::rows::{Row, Value};
78
79 struct MockSingle(i64);
80 impl CatalogQuerier for MockSingle {
81 fn fetch(&self, _: CatalogQuery, _: &[&str]) -> Result<Vec<Row>, CatalogError> {
82 Ok(vec![
83 Row::new().with("server_version_num", Value::Integer(self.0)),
84 ])
85 }
86 }
87
88 #[test]
89 fn detects_each_supported_major() {
90 for (n, v) in [
91 (140_005, PgVersion::Pg14),
92 (150_002, PgVersion::Pg15),
93 (160_000, PgVersion::Pg16),
94 (170_001, PgVersion::Pg17),
95 (180_000, PgVersion::Pg18),
96 ] {
97 assert_eq!(PgVersion::detect(&MockSingle(n)).unwrap(), v);
98 }
99 }
100
101 #[test]
102 fn detects_pg18() {
103 assert_eq!(
104 PgVersion::detect(&MockSingle(180_000)).unwrap(),
105 PgVersion::Pg18,
106 );
107 }
108
109 #[test]
110 fn rejects_unsupported() {
111 let err = PgVersion::detect(&MockSingle(130_004)).unwrap_err();
112 assert!(matches!(err, CatalogError::UnsupportedPgVersion(13)));
113 let err2 = PgVersion::detect(&MockSingle(190_000)).unwrap_err();
114 assert!(matches!(err2, CatalogError::UnsupportedPgVersion(19)));
115 }
116}