use super::{SqlGraphEntity, SqlGraphIdentifier, ToSql};
use core::convert::TryFrom;
use std::collections::HashMap;
#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct ControlFile {
pub comment: String,
pub default_version: String,
pub module_pathname: Option<String>,
pub relocatable: bool,
pub superuser: bool,
pub schema: Option<String>,
}
impl ControlFile {
pub fn from_str(input: &str) -> Result<Self, ControlFileError> {
let mut temp = HashMap::new();
for line in input.lines() {
let parts: Vec<&str> = line.split('=').collect();
if parts.len() != 2 {
continue;
}
let (k, v) = (parts.get(0).unwrap().trim(), parts.get(1).unwrap().trim());
let v = v.trim_start_matches('\'');
let v = v.trim_end_matches('\'');
temp.insert(k, v);
}
Ok(ControlFile {
comment: temp
.get("comment")
.ok_or(ControlFileError::MissingField { field: "comment" })?
.to_string(),
default_version: temp
.get("default_version")
.ok_or(ControlFileError::MissingField { field: "default_version" })?
.to_string(),
module_pathname: temp.get("module_pathname").map(|v| v.to_string()),
relocatable: temp
.get("relocatable")
.ok_or(ControlFileError::MissingField { field: "relocatable" })?
== &"true",
superuser: temp
.get("superuser")
.ok_or(ControlFileError::MissingField { field: "superuser" })?
== &"true",
schema: temp.get("schema").map(|v| v.to_string()),
})
}
}
impl From<ControlFile> for SqlGraphEntity {
fn from(val: ControlFile) -> Self {
SqlGraphEntity::ExtensionRoot(val)
}
}
#[derive(Debug, Clone)]
pub enum ControlFileError {
MissingField { field: &'static str },
}
impl std::fmt::Display for ControlFileError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ControlFileError::MissingField { field } => {
write!(f, "Missing field in control file! Please add `{}`.", field)?;
}
};
Ok(())
}
}
impl std::error::Error for ControlFileError {}
impl TryFrom<&str> for ControlFile {
type Error = ControlFileError;
fn try_from(input: &str) -> Result<Self, Self::Error> {
Self::from_str(input)
}
}
impl ToSql for ControlFile {
fn to_sql(&self, _context: &super::PgrxSql) -> eyre::Result<String> {
let sql = format!(
"\
/* \n\
This file is auto generated by pgrx.\n\
\n\
The ordering of items is not stable, it is driven by a dependency graph.\n\
*/\
"
);
Ok(sql)
}
}
impl SqlGraphIdentifier for ControlFile {
fn dot_identifier(&self) -> String {
format!("extension root")
}
fn rust_identifier(&self) -> String {
format!("root")
}
fn file(&self) -> Option<&'static str> {
None
}
fn line(&self) -> Option<u32> {
None
}
}