Skip to main content

uqa_sql/catalog/index/
enforced_key.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Unified descriptors for enforced table keys and standalone unique indexes.
8use crate::ast::{Expr, IndexKey, TableKeyConstraint};
9
10/// Runtime key enforcement keeps index predicates separate from SQL constraints.
11#[derive(Debug, Clone)]
12pub struct EnforcedKey {
13    pub constraint: TableKeyConstraint,
14    pub keys: Vec<IndexKey>,
15    pub index: Option<uqa_core::RelationIdentity>,
16    pub index_catalog: Option<super::IndexCatalogIdentity>,
17    /// Ordered parent incarnations used to bind a partition-root arbiter to its local physical index.
18    pub index_ancestors: Vec<[u8; 16]>,
19    pub predicate: Option<Box<Expr>>,
20    pub constraint_owned: bool,
21}
22
23impl std::ops::Deref for EnforcedKey {
24    type Target = TableKeyConstraint;
25
26    fn deref(&self) -> &Self::Target {
27        &self.constraint
28    }
29}
30
31impl From<TableKeyConstraint> for EnforcedKey {
32    fn from(constraint: TableKeyConstraint) -> Self {
33        Self {
34            keys: constraint
35                .columns
36                .iter()
37                .cloned()
38                .map(IndexKey::Column)
39                .collect(),
40            index: None,
41            index_catalog: None,
42            index_ancestors: Vec::new(),
43            constraint,
44            predicate: None,
45            constraint_owned: true,
46        }
47    }
48}
49
50/// Foreign keys may reference only non-partial unique keys composed entirely of ordinary columns.
51pub fn referenceable_keys(keys: Vec<EnforcedKey>) -> Vec<TableKeyConstraint> {
52    keys.into_iter()
53        .filter(|key| key.predicate.is_none() && key.keys.iter().all(|key| key.column().is_some()))
54        .map(|key| key.constraint)
55        .collect()
56}
57
58#[cfg(test)]
59mod tests;