uqa_sql/catalog/events/
persistence.rs1use super::{RuleCatalog, StoredRule, StoredTrigger, TriggerCatalog};
9use crate::ast::RelationPersistence;
10use serde::{Deserialize, Serialize};
11use uqa_core::RelationIdentity;
12pub const RULE_CATALOG_FORMAT_VERSION: u32 = 3;
13pub trait EventRelationPersistence {
14 fn rule_relation_is_temporary(&self, relation: &RelationIdentity) -> bool;
15 fn trigger_relation_persistence(
16 &self,
17 relation: &RelationIdentity,
18 ) -> Option<RelationPersistence>;
19}
20#[derive(Default, Serialize, Deserialize)]
21pub struct StoredTriggerCatalog {
22 #[serde(default, skip_serializing_if = "Vec::is_empty")]
23 pub triggers: Vec<StoredTrigger>,
24}
25
26#[derive(Default, Serialize, Deserialize)]
27pub struct StoredRuleCatalog {
28 #[serde(default)]
29 pub format_version: u32,
30 #[serde(default, skip_serializing_if = "Vec::is_empty")]
31 pub rules: Vec<StoredRule>,
32}
33
34pub fn stored_rules_snapshot(
35 rules: &RuleCatalog,
36 relations: &dyn EventRelationPersistence,
37) -> StoredRuleCatalog {
38 StoredRuleCatalog {
39 format_version: RULE_CATALOG_FORMAT_VERSION,
40 rules: rules
41 .iter()
42 .filter(|(relation, _)| !relations.rule_relation_is_temporary(relation))
43 .flat_map(|(_, entries)| entries.values().cloned())
44 .collect(),
45 }
46}
47
48pub fn stored_triggers_snapshot(
49 triggers: &TriggerCatalog,
50 relations: &dyn EventRelationPersistence,
51) -> StoredTriggerCatalog {
52 StoredTriggerCatalog {
53 triggers: triggers
54 .iter()
55 .filter(|(relation, _)| {
56 relations
57 .trigger_relation_persistence(relation)
58 .is_some_and(|persistence| persistence != RelationPersistence::Temporary)
59 })
60 .flat_map(|(_, entries)| entries.values().cloned())
61 .collect(),
62 }
63}
64
65pub fn rule_catalog_requires_migration(
66 format_version: u32,
67 allows_migration: bool,
68) -> Result<bool, String> {
69 if format_version > RULE_CATALOG_FORMAT_VERSION {
70 return Err(format!(
71 "rule catalog format {format_version} is newer than supported format {RULE_CATALOG_FORMAT_VERSION}"
72 ));
73 }
74 let migrating_catalog = format_version < RULE_CATALOG_FORMAT_VERSION;
75 if migrating_catalog && !allows_migration {
76 return Err("rule catalog requires an initial-open format migration".into());
77 }
78
79 Ok(migrating_catalog)
80}
81
82#[cfg(test)]
83mod tests;