1use super::{
4 Catalog, DepKind, ObjRef, PG_NAMESPACE, PG_OPCLASS, PG_OPERATOR, PG_PROC, PG_TYPE, is_pinned,
5};
6
7pub const PG_AM: u32 = 2601;
9pub const PG_AMOP: u32 = 2602;
11pub const PG_AMPROC: u32 = 2603;
13pub const PG_OPFAMILY: u32 = 2753;
15
16#[derive(Clone, Debug, PartialEq, Eq)]
18pub struct OpFamily {
19 pub oid: u32,
21 pub method: u32,
23 pub name: String,
25 pub namespace: u32,
27 pub owner: u32,
29}
30
31#[derive(Clone, Debug, PartialEq, Eq)]
33pub struct OpClass {
34 pub oid: u32,
36 pub method: u32,
38 pub name: String,
40 pub namespace: u32,
42 pub owner: u32,
44 pub family: u32,
46 pub intype: u32,
48 pub default: bool,
50 pub keytype: u32,
52}
53
54#[derive(Clone, Debug, PartialEq, Eq)]
56pub struct AmOp {
57 pub oid: u32,
59 pub family: u32,
61 pub left: u32,
63 pub right: u32,
65 pub strategy: i16,
67 pub purpose: u8,
69 pub operator: u32,
71 pub method: u32,
73 pub sortfamily: u32,
75}
76
77#[derive(Clone, Debug, PartialEq, Eq)]
79pub struct AmProc {
80 pub oid: u32,
82 pub family: u32,
84 pub left: u32,
86 pub right: u32,
88 pub number: i16,
90 pub function: u32,
92}
93
94#[derive(Clone, Debug, PartialEq, Eq)]
96pub struct MemberLink {
97 pub hard: bool,
99 pub owner: ObjRef,
101 pub inputs: Vec<u32>,
103}
104
105impl MemberLink {
106 fn kind(&self) -> DepKind {
108 if self.hard { DepKind::Normal } else { DepKind::Auto }
109 }
110
111 fn needs_type(&self, ty: u32) -> bool {
113 !is_pinned(ObjRef::new(PG_TYPE, ty)) && !self.inputs.contains(&ty)
114 }
115}
116
117impl Catalog {
118 pub fn create_opfamily(&mut self, mut new: OpFamily) -> u32 {
120 let oid = self.new_oid();
121 new.oid = oid;
122 let me = ObjRef::new(PG_OPFAMILY, oid);
123 self.depend(me, ObjRef::new(PG_AM, new.method), DepKind::Auto);
124 self.depend(me, ObjRef::new(PG_NAMESPACE, new.namespace), DepKind::Normal);
125 self.opfamilies.insert(oid, new);
126 oid
127 }
128
129 pub fn create_opclass(&mut self, mut new: OpClass) -> u32 {
131 let oid = self.new_oid();
132 new.oid = oid;
133 self.opclasses.insert(oid, new);
134 oid
135 }
136
137 pub fn opclass_depends(&mut self, oid: u32) {
139 let Some(class) = self.opclasses.get(&oid) else { return };
140 let me = ObjRef::new(PG_OPCLASS, oid);
141 let mut refs = vec![
142 (ObjRef::new(PG_NAMESPACE, class.namespace), DepKind::Normal),
143 (ObjRef::new(PG_OPFAMILY, class.family), DepKind::Auto),
144 (ObjRef::new(PG_TYPE, class.intype), DepKind::Normal),
145 ];
146 if class.keytype != 0 {
147 refs.push((ObjRef::new(PG_TYPE, class.keytype), DepKind::Normal));
148 }
149 for (referenced, kind) in refs {
150 self.depend(me, referenced, kind);
151 }
152 }
153
154 pub fn add_amop(&mut self, mut new: AmOp, link: &MemberLink) -> u32 {
156 let oid = self.new_oid();
157 new.oid = oid;
158 let me = ObjRef::new(PG_AMOP, oid);
159 self.depend(me, ObjRef::new(PG_OPERATOR, new.operator), link.kind());
160 self.member_depends(me, link, new.left, new.right);
161 if new.sortfamily != 0 {
162 self.depend(me, ObjRef::new(PG_OPFAMILY, new.sortfamily), link.kind());
163 }
164 self.amops.insert(oid, new);
165 oid
166 }
167
168 pub fn add_amproc(&mut self, mut new: AmProc, link: &MemberLink) -> u32 {
170 let oid = self.new_oid();
171 new.oid = oid;
172 let me = ObjRef::new(PG_AMPROC, oid);
173 self.depend(me, ObjRef::new(PG_PROC, new.function), link.kind());
174 self.member_depends(me, link, new.left, new.right);
175 self.amprocs.insert(oid, new);
176 oid
177 }
178
179 fn member_depends(&mut self, me: ObjRef, link: &MemberLink, left: u32, right: u32) {
181 let owner = if link.hard { DepKind::Internal } else { DepKind::Auto };
182 self.depend(me, link.owner, owner);
183 if link.needs_type(left) {
184 self.depend(me, ObjRef::new(PG_TYPE, left), link.kind());
185 }
186 if left != right && link.needs_type(right) {
187 self.depend(me, ObjRef::new(PG_TYPE, right), link.kind());
188 }
189 }
190
191 pub fn alter_opfamily(&mut self, oid: u32, change: impl FnOnce(&mut OpFamily)) {
193 if let Some(family) = self.opfamilies.get_mut(&oid) {
194 change(family);
195 }
196 }
197
198 pub fn alter_opclass(&mut self, oid: u32, change: impl FnOnce(&mut OpClass)) {
200 if let Some(class) = self.opclasses.get_mut(&oid) {
201 change(class);
202 }
203 }
204
205 pub fn set_opcf_namespace(&mut self, family: bool, oid: u32, namespace: u32) {
207 let (class, old) = if family {
208 let row = self.opfamilies.get_mut(&oid);
209 (PG_OPFAMILY, row.map(|f| std::mem::replace(&mut f.namespace, namespace)))
210 } else {
211 let row = self.opclasses.get_mut(&oid);
212 (PG_OPCLASS, row.map(|c| std::mem::replace(&mut c.namespace, namespace)))
213 };
214 if let Some(old) = old {
215 self.change_namespace_dependency(ObjRef::new(class, oid), old, namespace);
216 }
217 }
218
219 pub fn opfamilies(&self) -> impl Iterator<Item = &OpFamily> {
221 self.opfamilies.values()
222 }
223
224 pub fn opfamily(&self, oid: u32) -> Option<&OpFamily> {
226 self.opfamilies.get(&oid)
227 }
228
229 pub fn opclasses(&self) -> impl Iterator<Item = &OpClass> {
231 self.opclasses.values()
232 }
233
234 pub fn opclass(&self, oid: u32) -> Option<&OpClass> {
236 self.opclasses.get(&oid)
237 }
238
239 pub fn amops(&self) -> impl Iterator<Item = &AmOp> {
241 self.amops.values()
242 }
243
244 pub fn amop(&self, oid: u32) -> Option<&AmOp> {
246 self.amops.get(&oid)
247 }
248
249 pub fn amprocs(&self) -> impl Iterator<Item = &AmProc> {
251 self.amprocs.values()
252 }
253
254 pub fn amproc(&self, oid: u32) -> Option<&AmProc> {
256 self.amprocs.get(&oid)
257 }
258}