reifydb_catalog/store/view/
get_pk_id.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::{PrimaryKeyId, QueryTransaction, ViewId, ViewKey};
5
6use crate::{CatalogStore, store::view::layout::view};
7
8impl CatalogStore {
9	/// Get the primary key ID for a view
10	/// Returns None if the view doesn't exist or has no primary key
11	pub async fn get_view_pk_id(
12		rx: &mut impl QueryTransaction,
13		view_id: ViewId,
14	) -> crate::Result<Option<PrimaryKeyId>> {
15		let multi = match rx.get(&ViewKey::encoded(view_id)).await? {
16			Some(v) => v,
17			None => return Ok(None),
18		};
19
20		let pk_id = view::LAYOUT.get_u64(&multi.values, view::PRIMARY_KEY);
21
22		if pk_id == 0 {
23			Ok(None)
24		} else {
25			Ok(Some(PrimaryKeyId(pk_id)))
26		}
27	}
28}
29
30#[cfg(test)]
31mod tests {
32	use reifydb_core::interface::{SourceId, ViewId};
33	use reifydb_engine::test_utils::create_test_command_transaction;
34	use reifydb_type::{Type, TypeConstraint};
35
36	use crate::{
37		CatalogStore,
38		primary_key::PrimaryKeyToCreate,
39		test_utils::ensure_test_namespace,
40		view::{ViewColumnToCreate, ViewToCreate},
41	};
42
43	#[tokio::test]
44	async fn test_get_view_pk_id_with_primary_key() {
45		let mut txn = create_test_command_transaction().await;
46		let namespace = ensure_test_namespace(&mut txn).await;
47
48		// Create a view
49		let view = CatalogStore::create_deferred_view(
50			&mut txn,
51			ViewToCreate {
52				fragment: None,
53				namespace: namespace.id,
54				name: "test_view".to_string(),
55				columns: vec![ViewColumnToCreate {
56					name: "id".to_string(),
57					constraint: TypeConstraint::unconstrained(Type::Uint8),
58					fragment: None,
59				}],
60			},
61		)
62		.await
63		.unwrap();
64
65		// Get column IDs for the view
66		let columns = CatalogStore::list_columns(&mut txn, view.id).await.unwrap();
67
68		// Create primary key
69		let pk_id = CatalogStore::create_primary_key(
70			&mut txn,
71			PrimaryKeyToCreate {
72				source: SourceId::View(view.id),
73				column_ids: vec![columns[0].id],
74			},
75		)
76		.await
77		.unwrap();
78
79		// Get the primary key ID
80		let retrieved_pk_id = CatalogStore::get_view_pk_id(&mut txn, view.id)
81			.await
82			.unwrap()
83			.expect("Primary key ID should exist");
84
85		assert_eq!(retrieved_pk_id, pk_id);
86	}
87
88	#[tokio::test]
89	async fn test_get_view_pk_id_without_primary_key() {
90		let mut txn = create_test_command_transaction().await;
91		let namespace = ensure_test_namespace(&mut txn).await;
92
93		// Create a view
94		let view = CatalogStore::create_deferred_view(
95			&mut txn,
96			ViewToCreate {
97				fragment: None,
98				namespace: namespace.id,
99				name: "test_view".to_string(),
100				columns: vec![ViewColumnToCreate {
101					name: "id".to_string(),
102					constraint: TypeConstraint::unconstrained(Type::Uint8),
103					fragment: None,
104				}],
105			},
106		)
107		.await
108		.unwrap();
109
110		// Get the primary key ID - should be None
111		let pk_id = CatalogStore::get_view_pk_id(&mut txn, view.id).await.unwrap();
112
113		assert!(pk_id.is_none());
114	}
115
116	#[tokio::test]
117	async fn test_get_view_pk_id_nonexistent_view() {
118		let mut txn = create_test_command_transaction().await;
119
120		// Get the primary key ID for non-existent view - should be None
121		let pk_id = CatalogStore::get_view_pk_id(&mut txn, ViewId(999)).await.unwrap();
122
123		assert!(pk_id.is_none());
124	}
125}