1use rupg_common::{Error, Object, Result, SqlState};
4
5use super::{Catalog, DepKind, ObjRef, PG_CLASS, PG_NAMESPACE};
6
7pub const PG_STATISTIC_EXT: u32 = 3381;
9
10#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct StatExt {
13 pub oid: u32,
15 pub name: String,
17 pub namespace: u32,
19 pub owner: u32,
21 pub relation: u32,
23 pub keys: Vec<i16>,
25 pub kinds: Vec<u8>,
27 pub target: Option<i16>,
29 pub exprs: Option<String>,
31}
32
33impl Catalog {
34 pub fn create_stat_ext(&mut self, mut new: StatExt, refs: &[ObjRef]) -> Result<u32> {
40 let oid = self.new_oid();
41 if self.stat_ext_by_name(new.namespace, &new.name).is_some() {
42 return Err(Error::new(
43 SqlState::UNIQUE_VIOLATION,
44 "duplicate key value violates unique constraint \"pg_statistic_ext_name_index\"",
45 )
46 .with_detail(format!(
47 "Key (stxname, stxnamespace)=({}, {}) already exists.",
48 new.name, new.namespace
49 ))
50 .with_object(Object::Schema, "pg_catalog")
51 .with_object(Object::Table, "pg_statistic_ext")
52 .with_object(Object::Constraint, "pg_statistic_ext_name_index"));
53 }
54 new.oid = oid;
55 let me = ObjRef::new(PG_STATISTIC_EXT, oid);
56 for &number in &new.keys {
57 self.depend(me, ObjRef::column(new.relation, number), DepKind::Auto);
58 }
59 if new.keys.is_empty() {
60 self.depend(me, ObjRef::new(PG_CLASS, new.relation), DepKind::Auto);
61 }
62 self.depend_on_expr(me, refs, new.relation, DepKind::Auto);
63 self.depend(me, ObjRef::new(PG_NAMESPACE, new.namespace), DepKind::Normal);
64 self.stat_exts.insert(oid, new);
65 Ok(oid)
66 }
67
68 pub fn stat_exts(&self) -> impl Iterator<Item = &StatExt> {
70 self.stat_exts.values()
71 }
72
73 pub fn stat_ext(&self, oid: u32) -> Option<&StatExt> {
75 self.stat_exts.get(&oid)
76 }
77
78 pub fn stat_ext_by_name(&self, namespace: u32, name: &str) -> Option<&StatExt> {
80 self.stat_exts.values().find(|s| s.namespace == namespace && s.name == name)
81 }
82
83 pub fn alter_stat_ext(&mut self, oid: u32, change: impl FnOnce(&mut StatExt)) {
85 if let Some(stat) = self.stat_exts.get_mut(&oid) {
86 change(stat);
87 }
88 }
89
90 pub fn set_stat_ext_namespace(&mut self, oid: u32, namespace: u32) {
92 let old =
93 self.stat_exts.get_mut(&oid).map(|s| std::mem::replace(&mut s.namespace, namespace));
94 if let Some(old) = old {
95 self.change_namespace_dependency(ObjRef::new(PG_STATISTIC_EXT, oid), old, namespace);
96 }
97 }
98}