elefant-tools 0.0.2

A library for doing things like pg_dump and pg_restore, with extra features, and probably more bugs.
Documentation
use crate::helpers::StringExt;
use crate::pg_interval::Interval;
use crate::quoting::AttemptedKeywordUsage::ColumnName;
use crate::quoting::{IdentifierQuoter, Quotable};
use serde::{Deserialize, Serialize};

#[derive(Debug, Eq, PartialEq, Clone, Default, Serialize, Deserialize)]
pub struct HypertableCompression {
    pub enabled: bool,
    pub segment_by_columns: Option<Vec<String>>,
    pub order_by_columns: Option<Vec<HypertableCompressionOrderedColumn>>,
    pub chunk_time_interval: Option<Interval>,
    pub compression_schedule_interval: Option<Interval>,
    pub compress_after: Option<Interval>,
}

#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
pub struct HypertableCompressionOrderedColumn {
    pub column_name: String,
    pub descending: bool,
    pub nulls_first: bool,
}

impl Default for HypertableCompressionOrderedColumn {
    fn default() -> Self {
        Self {
            column_name: "".to_string(),
            descending: true,
            nulls_first: true,
        }
    }
}

impl HypertableCompression {
    pub fn add_compression_settings(
        &self,
        sql: &mut String,
        escaped_relation_name: &str,
        identifier_quoter: &IdentifierQuoter,
    ) {
        sql.push_str(escaped_relation_name);
        sql.push_str(" set (\n\ttimescaledb.compress = ");
        sql.push_str(&self.enabled.to_string());

        if let Some(segment_by) = &self.segment_by_columns {
            sql.push_str(",\n\ttimescaledb.compress_segmentby = '");
            sql.push_join(
                ", ",
                segment_by
                    .iter()
                    .map(|c| c.quote(identifier_quoter, ColumnName)),
            );
            sql.push('\'');
        }

        if let Some(order_by) = &self.order_by_columns {
            sql.push_str(",\n\ttimescaledb.compress_orderby = '");
            for (idx, order_by) in order_by.iter().enumerate() {
                if idx > 0 {
                    sql.push_str(", ");
                }
                sql.push_str(&order_by.column_name.quote(identifier_quoter, ColumnName));
                if !order_by.descending {
                    sql.push_str(" ASC");
                } else {
                    sql.push_str(" DESC");
                }
                if order_by.nulls_first {
                    sql.push_str(" NULLS FIRST");
                } else {
                    sql.push_str(" NULLS LAST");
                }
            }
            sql.push('\'');
        }

        if let Some(chunk_time_interval) = self.chunk_time_interval {
            sql.push_str(",\n\ttimescaledb.compress_chunk_time_interval = '");
            sql.push_str(&chunk_time_interval.to_postgres());
            sql.push('\'');
        }

        sql.push_str("\n);");

        if let Some(compress_after) = self.compress_after {
            sql.push_str("\nselect public.add_compression_policy('");
            sql.push_str(escaped_relation_name);
            sql.push_str("', compress_after => INTERVAL '");
            sql.push_str(&compress_after.to_postgres());
            sql.push('\'');

            if let Some(schedule_interval) = self.compression_schedule_interval {
                sql.push_str(", schedule_interval => INTERVAL '");
                sql.push_str(&schedule_interval.to_postgres());
                sql.push('\'');
            }

            sql.push_str(");");
        }
    }
}