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}
18
19impl PgVersion {
20 pub fn detect(querier: &dyn CatalogQuerier) -> Result<Self, CatalogError> {
22 let rows = querier.fetch(CatalogQuery::PgVersion, &[])?;
23 let row = rows.into_iter().next().ok_or(CatalogError::MissingResult {
24 query: CatalogQuery::PgVersion,
25 })?;
26 let n = row.get_int(CatalogQuery::PgVersion, "server_version_num")?;
27 Self::from_server_version_num(n)
28 }
29
30 pub fn from_server_version_num(n: i64) -> Result<Self, CatalogError> {
34 let major = n / 10_000;
35 match major {
36 14 => Ok(Self::Pg14),
37 15 => Ok(Self::Pg15),
38 16 => Ok(Self::Pg16),
39 17 => Ok(Self::Pg17),
40 v => Err(CatalogError::UnsupportedPgVersion(
41 v.try_into().unwrap_or(0),
42 )),
43 }
44 }
45
46 #[must_use]
48 pub const fn as_tag(self) -> &'static str {
49 match self {
50 Self::Pg14 => "pg14",
51 Self::Pg15 => "pg15",
52 Self::Pg16 => "pg16",
53 Self::Pg17 => "pg17",
54 }
55 }
56
57 #[must_use]
59 pub const fn major(self) -> u32 {
60 match self {
61 Self::Pg14 => 14,
62 Self::Pg15 => 15,
63 Self::Pg16 => 16,
64 Self::Pg17 => 17,
65 }
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use crate::catalog::rows::{Row, Value};
73
74 struct MockSingle(i64);
75 impl CatalogQuerier for MockSingle {
76 fn fetch(&self, _: CatalogQuery, _: &[&str]) -> Result<Vec<Row>, CatalogError> {
77 Ok(vec![
78 Row::new().with("server_version_num", Value::Integer(self.0)),
79 ])
80 }
81 }
82
83 #[test]
84 fn detects_each_supported_major() {
85 for (n, v) in [
86 (140_005, PgVersion::Pg14),
87 (150_002, PgVersion::Pg15),
88 (160_000, PgVersion::Pg16),
89 (170_001, PgVersion::Pg17),
90 ] {
91 assert_eq!(PgVersion::detect(&MockSingle(n)).unwrap(), v);
92 }
93 }
94
95 #[test]
96 fn rejects_unsupported() {
97 let err = PgVersion::detect(&MockSingle(130_004)).unwrap_err();
98 assert!(matches!(err, CatalogError::UnsupportedPgVersion(13)));
99 let err2 = PgVersion::detect(&MockSingle(180_000)).unwrap_err();
100 assert!(matches!(err2, CatalogError::UnsupportedPgVersion(18)));
101 }
102}