reifydb_catalog/store/primary_key/
list.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use reifydb_core::interface::{PrimaryKeyDef, QueryTransaction};
5
6use crate::{
7	CatalogStore,
8	store::primary_key::layout::{primary_key, primary_key::deserialize_column_ids},
9};
10
11pub struct PrimaryKeyInfo {
12	pub def: PrimaryKeyDef,
13	pub source_id: u64,
14}
15
16impl CatalogStore {
17	pub async fn list_primary_keys(rx: &mut impl QueryTransaction) -> crate::Result<Vec<PrimaryKeyInfo>> {
18		use std::ops::Bound;
19
20		use reifydb_core::{
21			EncodedKeyRange,
22			interface::{Key, PrimaryKeyKey},
23		};
24
25		let mut result = Vec::new();
26
27		// Scan all primary key entries from storage
28		// Note: Key encoding uses reverse order, so MAX encodes smaller
29		// than 0
30		let primary_key_range = {
31			let start_key = PrimaryKeyKey::encoded(reifydb_core::interface::PrimaryKeyId(u64::MAX));
32			let end_key = PrimaryKeyKey::encoded(reifydb_core::interface::PrimaryKeyId(0));
33
34			EncodedKeyRange::new(Bound::Included(start_key), Bound::Included(end_key))
35		};
36
37		// Collect entries first to avoid borrow checker issues
38		let batch = rx.range(primary_key_range).await?;
39
40		for entry in batch.items {
41			// Decode the primary key ID from the key
42			if let Some(key) = Key::decode(&entry.key) {
43				if let Key::PrimaryKey(pk_key) = key {
44					// Get the source ID from the primary
45					// key record
46					let source_id = primary_key::LAYOUT.get_u64(&entry.values, primary_key::SOURCE);
47
48					// Deserialize column IDs
49					let column_ids_blob =
50						primary_key::LAYOUT.get_blob(&entry.values, primary_key::COLUMN_IDS);
51					let column_ids = deserialize_column_ids(&column_ids_blob);
52
53					// Fetch full ColumnDef for each column
54					// ID
55					let mut columns = Vec::new();
56					for column_id in column_ids {
57						let column_def = Self::get_column(rx, column_id).await?;
58						columns.push(reifydb_core::interface::ColumnDef {
59							id: column_def.id,
60							name: column_def.name,
61							constraint: column_def.constraint,
62							policies: column_def.policies,
63							index: column_def.index,
64							auto_increment: column_def.auto_increment,
65							dictionary_id: None,
66						});
67					}
68
69					let pk_def = PrimaryKeyDef {
70						id: pk_key.primary_key,
71						columns,
72					};
73
74					result.push(PrimaryKeyInfo {
75						def: pk_def,
76						source_id,
77					});
78				}
79			}
80		}
81
82		Ok(result)
83	}
84
85	pub async fn list_primary_key_columns(rx: &mut impl QueryTransaction) -> crate::Result<Vec<(u64, u64, usize)>> {
86		use std::ops::Bound;
87
88		use reifydb_core::{
89			EncodedKeyRange,
90			interface::{Key, PrimaryKeyKey},
91		};
92
93		let mut result = Vec::new();
94
95		// Scan all primary key entries from storage using same approach
96		// as list_primary_keys
97		let primary_key_range = {
98			let start_key = PrimaryKeyKey::encoded(reifydb_core::interface::PrimaryKeyId(u64::MAX));
99			let end_key = PrimaryKeyKey::encoded(reifydb_core::interface::PrimaryKeyId(0));
100
101			EncodedKeyRange::new(Bound::Included(start_key), Bound::Included(end_key))
102		};
103
104		// Collect entries first to avoid borrow checker issues
105		let batch = rx.range(primary_key_range).await?;
106
107		for entry in batch.items {
108			// Decode the primary key ID from the key
109			if let Some(key) = Key::decode(&entry.key) {
110				if let Key::PrimaryKey(pk_key) = key {
111					// Deserialize column IDs from the
112					// primary key record
113					let column_ids_blob =
114						primary_key::LAYOUT.get_blob(&entry.values, primary_key::COLUMN_IDS);
115					let column_ids = deserialize_column_ids(&column_ids_blob);
116
117					// Add each column with its position
118					for (position, column_id) in column_ids.iter().enumerate() {
119						result.push((
120							pk_key.primary_key.0, // primary key id
121							column_id.0,          // column id
122							position,             // position in the primary key
123						));
124					}
125				}
126			}
127		}
128
129		Ok(result)
130	}
131}