1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//
// Unified Query Algebra
//
// Copyright (c) 2023-2026 Cognica, Inc.
//
//! Borrowed catalog identities and comparison support for SQL value consumers.
use super::enums::{EnumTypeComparisonStates, EnumTypeLabels};
use super::Result;
use std::sync::Arc;
use uqa_core::EnumValue;
/// Type metadata and enum support used to observe already admitted SQL values. Implementations borrow one statement catalog generation and never invoke type input.
pub trait SQLValueCatalog {
/// The declared type for a physical OID, including domains, arrays and composites.
fn value_type_by_oid(&self, _oid: u32) -> Result<Option<crate::ColumnType>> {
Ok(None)
}
/// The current descriptor of an admitted composite value.
fn value_composite_type(
&self,
_oid: u32,
) -> Result<Option<Arc<super::composites::CompositeTypeDescriptor>>> {
Ok(None)
}
/// The session's comparison support functions, shared by declared type across nested array and record calls. Pure catalog readers do not own runtime state.
fn enum_type_comparison_states(&self) -> Option<&EnumTypeComparisonStates> {
None
}
/// The labels of one enum type in the statement's catalog generation, or `None` when the catalog has no such type.
fn enum_type_labels(&self, type_oid: u32) -> Result<Option<Arc<EnumTypeLabels>>>;
/// Resolve an already admitted physical label OID across enum types. Output uses the label's actual identity even if a retained tuple now declares another enum type; it does not repeat input safety checks.
fn enum_value_by_oid(&self, _label_oid: u32) -> Result<Option<EnumValue>> {
Ok(None)
}
/// The actual enum type and zero-based label position of an admitted physical OID in this generation. Positions have declaration/key order and avoid copying label keys for comparison.
fn enum_label_position(&self, _label_oid: u32) -> Result<Option<(u32, usize)>> {
Ok(None)
}
/// Whether the current transaction added this label to a type that it did not create. `PostgreSQL` rejects such a label until the transaction commits.
fn enum_label_uncommitted(&self, label_oid: u32) -> bool;
/// `format_type_be` of the type, which qualifies a type hidden by the search path.
fn enum_type_name(&self, type_oid: u32) -> Result<Option<String>>;
/// Whether the statement catalog defines any enum type; binding skips enum literal validation otherwise.
fn has_enum_types(&self) -> bool;
}
/// Adapt a scalar context without requiring embedders that only provide domain or composite metadata to implement enum support.
pub struct EngineValueCatalog<'a>(pub &'a dyn super::EngineHook);
impl SQLValueCatalog for EngineValueCatalog<'_> {
fn value_type_by_oid(&self, oid: u32) -> Result<Option<crate::ColumnType>> {
self.0
.resolve_type_oid(oid)
.map_err(crate::SQLError::Internal)
}
fn value_composite_type(
&self,
oid: u32,
) -> Result<Option<Arc<super::composites::CompositeTypeDescriptor>>> {
self.0
.composite_types()
.map(|catalog| catalog.composite_type(oid))
.transpose()
.map(Option::flatten)
}
fn enum_type_comparison_states(&self) -> Option<&EnumTypeComparisonStates> {
self.0.enum_labels()?.enum_type_comparison_states()
}
fn enum_type_labels(&self, oid: u32) -> Result<Option<Arc<EnumTypeLabels>>> {
self.0
.enum_labels()
.map(|catalog| catalog.enum_type_labels(oid))
.transpose()
.map(Option::flatten)
}
fn enum_value_by_oid(&self, oid: u32) -> Result<Option<EnumValue>> {
self.0
.enum_labels()
.map(|catalog| catalog.enum_value_by_oid(oid))
.transpose()
.map(Option::flatten)
}
fn enum_label_position(&self, oid: u32) -> Result<Option<(u32, usize)>> {
self.0
.enum_labels()
.map(|catalog| catalog.enum_label_position(oid))
.transpose()
.map(Option::flatten)
}
fn enum_label_uncommitted(&self, oid: u32) -> bool {
self.0
.enum_labels()
.is_some_and(|catalog| catalog.enum_label_uncommitted(oid))
}
fn enum_type_name(&self, oid: u32) -> Result<Option<String>> {
self.0
.enum_labels()
.map(|catalog| catalog.enum_type_name(oid))
.transpose()
.map(Option::flatten)
}
fn has_enum_types(&self) -> bool {
self.0
.enum_labels()
.is_some_and(SQLValueCatalog::has_enum_types)
}
}