use crate::database::{Database, DATABASE};
use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)]
pub struct Index {
condition: String,
pub name: String,
schema: Option<String>,
table: String,
unique: bool,
definition: String,
}
impl Index {
pub fn exists(&self) -> bool {
let db = DATABASE.get_or_init(|| Database::new());
let row = db
.client()
.query_one(
"
SELECT EXISTS (
SELECT 1 FROM pg_indexes
WHERE indexname = $1 AND schemaname = $2 AND tablename = $3
)",
&[&self.name, &self.schema, &self.table],
)
.unwrap();
row.get(0)
}
fn create(&self, is_concurent: bool) -> String {
let db = DATABASE.get_or_init(|| Database::new());
let mut already_or_not = "already ";
if !self.exists() {
already_or_not = "";
let concurrently = match is_concurent {
true => "CONCURRENTLY ",
false => "",
};
let unique = match self.unique {
true => "UNIQUE ",
false => "",
};
let table = match &self.schema {
Some(schema) => {
let t = self.table.clone();
format!("{schema}.{t}")
}
None => self.table.clone(),
};
let name = self.name.clone();
let definition = self.definition.clone();
let _ = db.client().execute(
format!(
"
CREATE {unique}INDEX {concurrently}{name}
ON {table} {definition}
"
)
.as_str(),
&[],
);
}
format!("index {already_or_not}created")
}
pub fn background_run(&self) -> String {
self.create(true)
}
pub fn final_run(&self) -> String {
self.create(false)
}
pub fn required(&self) -> bool {
let db = DATABASE.get_or_init(|| Database::new());
db.client()
.query_one(self.condition.as_str(), &[])
.unwrap()
.get(0)
}
}
pub fn test_setup<T>(query: &T)
where
T: ?Sized + postgres::ToStatement,
{
let db = DATABASE.get_or_init(|| Database::new());
let mut client = db.client();
let _ = client.execute(query, &[]);
}