reifydb_catalog/store/view/
find.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::{
5	MultiVersionValues, NamespaceId, NamespaceViewKey, QueryTransaction, ViewDef, ViewId, ViewKey, ViewKind,
6};
7
8use crate::{
9	CatalogStore,
10	store::view::layout::{view, view_namespace},
11};
12
13impl CatalogStore {
14	pub async fn find_view(rx: &mut impl QueryTransaction, id: ViewId) -> crate::Result<Option<ViewDef>> {
15		let Some(multi) = rx.get(&ViewKey::encoded(id)).await? else {
16			return Ok(None);
17		};
18
19		let row = multi.values;
20		let id = ViewId(view::LAYOUT.get_u64(&row, view::ID));
21		let namespace = NamespaceId(view::LAYOUT.get_u64(&row, view::NAMESPACE));
22		let name = view::LAYOUT.get_utf8(&row, view::NAME).to_string();
23
24		let kind = match view::LAYOUT.get_u8(&row, view::KIND) {
25			0 => ViewKind::Deferred,
26			1 => ViewKind::Transactional,
27			_ => unimplemented!(),
28		};
29
30		Ok(Some(ViewDef {
31			id,
32			name,
33			namespace,
34			kind,
35			columns: Self::list_columns(rx, id).await?,
36			primary_key: Self::find_view_primary_key(rx, id).await?,
37		}))
38	}
39
40	pub async fn find_view_by_name(
41		rx: &mut impl QueryTransaction,
42		namespace: NamespaceId,
43		name: impl AsRef<str>,
44	) -> crate::Result<Option<ViewDef>> {
45		let name = name.as_ref();
46		let batch = rx.range(NamespaceViewKey::full_scan(namespace)).await?;
47		let Some(view) = batch.items.iter().find_map(|multi: &MultiVersionValues| {
48			let row = &multi.values;
49			let view_name = view_namespace::LAYOUT.get_utf8(row, view_namespace::NAME);
50			if name == view_name {
51				Some(ViewId(view_namespace::LAYOUT.get_u64(row, view_namespace::ID)))
52			} else {
53				None
54			}
55		}) else {
56			return Ok(None);
57		};
58
59		Ok(Some(Self::get_view(rx, view).await?))
60	}
61}
62
63#[cfg(test)]
64mod tests {
65	use reifydb_core::interface::{NamespaceId, ViewId};
66	use reifydb_engine::test_utils::create_test_command_transaction;
67
68	use crate::{
69		CatalogStore,
70		test_utils::{create_namespace, create_view, ensure_test_namespace},
71	};
72
73	#[tokio::test]
74	async fn test_ok() {
75		let mut txn = create_test_command_transaction().await;
76		ensure_test_namespace(&mut txn).await;
77		create_namespace(&mut txn, "namespace_one").await;
78		create_namespace(&mut txn, "namespace_two").await;
79		create_namespace(&mut txn, "namespace_three").await;
80
81		create_view(&mut txn, "namespace_one", "view_one", &[]).await;
82		create_view(&mut txn, "namespace_two", "view_two", &[]).await;
83		create_view(&mut txn, "namespace_three", "view_three", &[]).await;
84
85		let result = CatalogStore::find_view_by_name(&mut txn, NamespaceId(1027), "view_two")
86			.await
87			.unwrap()
88			.unwrap();
89		assert_eq!(result.id, ViewId(1026));
90		assert_eq!(result.namespace, NamespaceId(1027));
91		assert_eq!(result.name, "view_two");
92	}
93
94	#[tokio::test]
95	async fn test_empty() {
96		let mut txn = create_test_command_transaction().await;
97
98		let result = CatalogStore::find_view_by_name(&mut txn, NamespaceId(1025), "some_view").await.unwrap();
99		assert!(result.is_none());
100	}
101
102	#[tokio::test]
103	async fn test_not_found_different_view() {
104		let mut txn = create_test_command_transaction().await;
105		ensure_test_namespace(&mut txn).await;
106		create_namespace(&mut txn, "namespace_one").await;
107		create_namespace(&mut txn, "namespace_two").await;
108		create_namespace(&mut txn, "namespace_three").await;
109
110		create_view(&mut txn, "namespace_one", "view_one", &[]).await;
111		create_view(&mut txn, "namespace_two", "view_two", &[]).await;
112		create_view(&mut txn, "namespace_three", "view_three", &[]).await;
113
114		let result =
115			CatalogStore::find_view_by_name(&mut txn, NamespaceId(1025), "view_four_two").await.unwrap();
116		assert!(result.is_none());
117	}
118
119	#[tokio::test]
120	async fn test_not_found_different_namespace() {
121		let mut txn = create_test_command_transaction().await;
122		ensure_test_namespace(&mut txn).await;
123		create_namespace(&mut txn, "namespace_one").await;
124		create_namespace(&mut txn, "namespace_two").await;
125		create_namespace(&mut txn, "namespace_three").await;
126
127		create_view(&mut txn, "namespace_one", "view_one", &[]).await;
128		create_view(&mut txn, "namespace_two", "view_two", &[]).await;
129		create_view(&mut txn, "namespace_three", "view_three", &[]).await;
130
131		let result = CatalogStore::find_view_by_name(&mut txn, NamespaceId(2), "view_two").await.unwrap();
132		assert!(result.is_none());
133	}
134}