reifydb_catalog/store/view/
set_pk.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::{
5	interface::{CommandTransaction, PrimaryKeyId, ViewId, ViewKey},
6	return_internal_error,
7};
8
9use crate::{CatalogStore, store::view::layout::view};
10
11impl CatalogStore {
12	/// Set the primary key ID for a view
13	/// Returns an internal error if the view doesn't exist
14	pub async fn set_view_primary_key(
15		txn: &mut impl CommandTransaction,
16		view_id: ViewId,
17		primary_key_id: PrimaryKeyId,
18	) -> crate::Result<()> {
19		let multi = match txn.get(&ViewKey::encoded(view_id)).await? {
20			Some(v) => v,
21			None => return_internal_error!(format!(
22				"View with ID {} not found when setting primary key. This indicates a critical catalog inconsistency.",
23				view_id.0
24			)),
25		};
26
27		let mut updated_row = multi.values.clone();
28		view::LAYOUT.set_u64(&mut updated_row, view::PRIMARY_KEY, primary_key_id.0);
29
30		txn.set(&ViewKey::encoded(view_id), updated_row).await?;
31
32		Ok(())
33	}
34}
35
36#[cfg(test)]
37mod tests {
38	use reifydb_core::interface::{PrimaryKeyId, ViewId};
39	use reifydb_engine::test_utils::create_test_command_transaction;
40	use reifydb_type::{Type, TypeConstraint};
41
42	use crate::{
43		CatalogStore,
44		store::view::{ViewColumnToCreate, ViewToCreate},
45		test_utils::ensure_test_namespace,
46	};
47
48	#[tokio::test]
49	async fn test_set_view_primary_key() {
50		let mut txn = create_test_command_transaction().await;
51		let namespace = ensure_test_namespace(&mut txn).await;
52
53		let view = CatalogStore::create_deferred_view(
54			&mut txn,
55			ViewToCreate {
56				fragment: None,
57				namespace: namespace.id,
58				name: "test_view".to_string(),
59				columns: vec![ViewColumnToCreate {
60					name: "id".to_string(),
61					constraint: TypeConstraint::unconstrained(Type::Uint8),
62					fragment: None,
63				}],
64			},
65		)
66		.await
67		.unwrap();
68
69		// Set primary key
70		CatalogStore::set_view_primary_key(&mut txn, view.id, PrimaryKeyId(42)).await.unwrap();
71
72		// The test succeeds if no error is thrown.
73		// In real usage, create_primary_key would create both the
74		// PrimaryKey record and update the view, and find_primary_key
75		// would find it.
76	}
77
78	#[tokio::test]
79	async fn test_set_view_primary_key_nonexistent() {
80		let mut txn = create_test_command_transaction().await;
81
82		// Try to set primary key on non-existent view
83		let result = CatalogStore::set_view_primary_key(&mut txn, ViewId(999), PrimaryKeyId(1)).await;
84
85		assert!(result.is_err());
86		let err = result.unwrap_err();
87		assert!(err.to_string().contains("View with ID 999 not found"));
88		assert!(err.to_string().contains("critical catalog inconsistency"));
89	}
90}