elefant_tools/models/
hypertable_compression.rs

1use crate::helpers::StringExt;
2use crate::pg_interval::Interval;
3use crate::quoting::AttemptedKeywordUsage::ColumnName;
4use crate::quoting::{IdentifierQuoter, Quotable};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Eq, PartialEq, Clone, Default, Serialize, Deserialize)]
8pub struct HypertableCompression {
9    pub enabled: bool,
10    pub segment_by_columns: Option<Vec<String>>,
11    pub order_by_columns: Option<Vec<HypertableCompressionOrderedColumn>>,
12    pub chunk_time_interval: Option<Interval>,
13    pub compression_schedule_interval: Option<Interval>,
14    pub compress_after: Option<Interval>,
15}
16
17#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
18pub struct HypertableCompressionOrderedColumn {
19    pub column_name: String,
20    pub descending: bool,
21    pub nulls_first: bool,
22}
23
24impl Default for HypertableCompressionOrderedColumn {
25    fn default() -> Self {
26        Self {
27            column_name: "".to_string(),
28            descending: true,
29            nulls_first: true,
30        }
31    }
32}
33
34impl HypertableCompression {
35    pub fn add_compression_settings(
36        &self,
37        sql: &mut String,
38        escaped_relation_name: &str,
39        identifier_quoter: &IdentifierQuoter,
40    ) {
41        sql.push_str(escaped_relation_name);
42        sql.push_str(" set (\n\ttimescaledb.compress = ");
43        sql.push_str(&self.enabled.to_string());
44
45        if let Some(segment_by) = &self.segment_by_columns {
46            sql.push_str(",\n\ttimescaledb.compress_segmentby = '");
47            sql.push_join(
48                ", ",
49                segment_by
50                    .iter()
51                    .map(|c| c.quote(identifier_quoter, ColumnName)),
52            );
53            sql.push('\'');
54        }
55
56        if let Some(order_by) = &self.order_by_columns {
57            sql.push_str(",\n\ttimescaledb.compress_orderby = '");
58            for (idx, order_by) in order_by.iter().enumerate() {
59                if idx > 0 {
60                    sql.push_str(", ");
61                }
62                sql.push_str(&order_by.column_name.quote(identifier_quoter, ColumnName));
63                if !order_by.descending {
64                    sql.push_str(" ASC");
65                } else {
66                    sql.push_str(" DESC");
67                }
68                if order_by.nulls_first {
69                    sql.push_str(" NULLS FIRST");
70                } else {
71                    sql.push_str(" NULLS LAST");
72                }
73            }
74            sql.push('\'');
75        }
76
77        if let Some(chunk_time_interval) = self.chunk_time_interval {
78            sql.push_str(",\n\ttimescaledb.compress_chunk_time_interval = '");
79            sql.push_str(&chunk_time_interval.to_postgres());
80            sql.push('\'');
81        }
82
83        sql.push_str("\n);");
84
85        if let Some(compress_after) = self.compress_after {
86            sql.push_str("\nselect public.add_compression_policy('");
87            sql.push_str(escaped_relation_name);
88            sql.push_str("', compress_after => INTERVAL '");
89            sql.push_str(&compress_after.to_postgres());
90            sql.push('\'');
91
92            if let Some(schedule_interval) = self.compression_schedule_interval {
93                sql.push_str(", schedule_interval => INTERVAL '");
94                sql.push_str(&schedule_interval.to_postgres());
95                sql.push('\'');
96            }
97
98            sql.push_str(");");
99        }
100    }
101}