Skip to main content

reifydb_core/interface/
resolved.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::sync::Arc;
5
6use reifydb_type::{
7	error::NumberOutOfRangeDescriptor,
8	fragment::Fragment,
9	value::{constraint::TypeConstraint, r#type::Type},
10};
11use serde::{Deserialize, Serialize};
12
13use super::catalog::{
14	column::Column, dictionary::Dictionary, namespace::Namespace, property::ColumnPropertyKind,
15	ringbuffer::RingBuffer, series::Series, table::Table, view::View, vtable::VTable,
16};
17
18#[derive(Debug, Clone)]
19pub enum ResolvedNamespace {
20	Local(Arc<ResolvedNamespaceInner>),
21	Remote(Arc<ResolvedNamespaceInner>),
22}
23
24#[derive(Debug)]
25pub struct ResolvedNamespaceInner {
26	identifier: Fragment,
27	def: Namespace,
28}
29
30impl ResolvedNamespace {
31	pub fn new(identifier: Fragment, def: Namespace) -> Self {
32		let is_remote = def.is_remote();
33		let inner = Arc::new(ResolvedNamespaceInner {
34			identifier,
35			def,
36		});
37		if is_remote {
38			Self::Remote(inner)
39		} else {
40			Self::Local(inner)
41		}
42	}
43
44	fn inner(&self) -> &ResolvedNamespaceInner {
45		match self {
46			Self::Local(inner) | Self::Remote(inner) => inner,
47		}
48	}
49
50	pub fn name(&self) -> &str {
51		self.inner().def.name()
52	}
53
54	pub fn def(&self) -> &Namespace {
55		&self.inner().def
56	}
57
58	pub fn fragment(&self) -> &Fragment {
59		&self.inner().identifier
60	}
61
62	pub fn is_remote(&self) -> bool {
63		matches!(self, Self::Remote(_))
64	}
65
66	pub fn address(&self) -> Option<&str> {
67		self.inner().def.address()
68	}
69
70	pub fn to_static(&self) -> ResolvedNamespace {
71		let inner = self.inner();
72		ResolvedNamespace::new(Fragment::internal(inner.identifier.text()), inner.def.clone())
73	}
74}
75
76#[derive(Debug, Clone)]
77pub struct ResolvedTable(Arc<ResolvedTableInner>);
78
79#[derive(Debug)]
80struct ResolvedTableInner {
81	pub identifier: Fragment,
82	pub namespace: ResolvedNamespace,
83	pub def: Table,
84}
85
86impl ResolvedTable {
87	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, def: Table) -> Self {
88		Self(Arc::new(ResolvedTableInner {
89			identifier,
90			namespace,
91			def,
92		}))
93	}
94
95	pub fn name(&self) -> &str {
96		&self.0.def.name
97	}
98
99	pub fn def(&self) -> &Table {
100		&self.0.def
101	}
102
103	pub fn namespace(&self) -> &ResolvedNamespace {
104		&self.0.namespace
105	}
106
107	pub fn identifier(&self) -> &Fragment {
108		&self.0.identifier
109	}
110
111	pub fn fully_qualified_name(&self) -> String {
112		format!("{}::{}", self.0.namespace.name(), self.name())
113	}
114
115	pub fn columns(&self) -> &[Column] {
116		&self.0.def.columns
117	}
118
119	pub fn find_column(&self, name: &str) -> Option<&Column> {
120		self.0.def.columns.iter().find(|c| c.name == name)
121	}
122
123	pub fn to_static(&self) -> ResolvedTable {
124		ResolvedTable(Arc::new(ResolvedTableInner {
125			identifier: Fragment::internal(self.0.identifier.text()),
126			namespace: self.0.namespace.clone(),
127			def: self.0.def.clone(),
128		}))
129	}
130}
131
132#[derive(Debug, Clone)]
133pub struct ResolvedTableVirtual(Arc<ResolvedTableVirtualInner>);
134
135#[derive(Debug)]
136struct ResolvedTableVirtualInner {
137	pub identifier: Fragment,
138	pub namespace: ResolvedNamespace,
139	pub def: VTable,
140}
141
142impl ResolvedTableVirtual {
143	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, def: VTable) -> Self {
144		Self(Arc::new(ResolvedTableVirtualInner {
145			identifier,
146			namespace,
147			def,
148		}))
149	}
150
151	pub fn name(&self) -> &str {
152		&self.0.def.name
153	}
154
155	pub fn def(&self) -> &VTable {
156		&self.0.def
157	}
158
159	pub fn namespace(&self) -> &ResolvedNamespace {
160		&self.0.namespace
161	}
162
163	pub fn identifier(&self) -> &Fragment {
164		&self.0.identifier
165	}
166
167	pub fn columns(&self) -> &[Column] {
168		&self.0.def.columns
169	}
170
171	pub fn to_static(&self) -> ResolvedTableVirtual {
172		ResolvedTableVirtual(Arc::new(ResolvedTableVirtualInner {
173			identifier: Fragment::internal(self.0.identifier.text()),
174			namespace: self.0.namespace.clone(),
175			def: self.0.def.clone(),
176		}))
177	}
178}
179
180#[derive(Debug, Clone)]
181pub struct ResolvedRingBuffer(Arc<ResolvedRingBufferInner>);
182
183#[derive(Debug)]
184struct ResolvedRingBufferInner {
185	pub identifier: Fragment,
186	pub namespace: ResolvedNamespace,
187	pub def: RingBuffer,
188}
189
190impl ResolvedRingBuffer {
191	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, def: RingBuffer) -> Self {
192		Self(Arc::new(ResolvedRingBufferInner {
193			identifier,
194			namespace,
195			def,
196		}))
197	}
198
199	pub fn name(&self) -> &str {
200		&self.0.def.name
201	}
202
203	pub fn def(&self) -> &RingBuffer {
204		&self.0.def
205	}
206
207	pub fn namespace(&self) -> &ResolvedNamespace {
208		&self.0.namespace
209	}
210
211	pub fn identifier(&self) -> &Fragment {
212		&self.0.identifier
213	}
214
215	pub fn fully_qualified_name(&self) -> String {
216		format!("{}::{}", self.0.namespace.name(), self.name())
217	}
218
219	pub fn columns(&self) -> &[Column] {
220		&self.0.def.columns
221	}
222
223	pub fn find_column(&self, name: &str) -> Option<&Column> {
224		self.0.def.columns.iter().find(|c| c.name == name)
225	}
226
227	pub fn to_static(&self) -> ResolvedRingBuffer {
228		ResolvedRingBuffer(Arc::new(ResolvedRingBufferInner {
229			identifier: Fragment::internal(self.0.identifier.text()),
230			namespace: self.0.namespace.clone(),
231			def: self.0.def.clone(),
232		}))
233	}
234}
235
236#[derive(Debug, Clone)]
237pub struct ResolvedDictionary(Arc<ResolvedDictionaryInner>);
238
239#[derive(Debug)]
240struct ResolvedDictionaryInner {
241	pub identifier: Fragment,
242	pub namespace: ResolvedNamespace,
243	pub def: Dictionary,
244}
245
246impl ResolvedDictionary {
247	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, def: Dictionary) -> Self {
248		Self(Arc::new(ResolvedDictionaryInner {
249			identifier,
250			namespace,
251			def,
252		}))
253	}
254
255	pub fn name(&self) -> &str {
256		&self.0.def.name
257	}
258
259	pub fn def(&self) -> &Dictionary {
260		&self.0.def
261	}
262
263	pub fn namespace(&self) -> &ResolvedNamespace {
264		&self.0.namespace
265	}
266
267	pub fn identifier(&self) -> &Fragment {
268		&self.0.identifier
269	}
270
271	pub fn fully_qualified_name(&self) -> String {
272		format!("{}::{}", self.0.namespace.name(), self.name())
273	}
274
275	pub fn to_static(&self) -> ResolvedDictionary {
276		ResolvedDictionary(Arc::new(ResolvedDictionaryInner {
277			identifier: Fragment::internal(self.0.identifier.text()),
278			namespace: self.0.namespace.clone(),
279			def: self.0.def.clone(),
280		}))
281	}
282}
283
284#[derive(Debug, Clone)]
285pub struct ResolvedSeries(Arc<ResolvedSeriesInner>);
286
287#[derive(Debug)]
288struct ResolvedSeriesInner {
289	pub identifier: Fragment,
290	pub namespace: ResolvedNamespace,
291	pub def: Series,
292}
293
294impl ResolvedSeries {
295	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, def: Series) -> Self {
296		Self(Arc::new(ResolvedSeriesInner {
297			identifier,
298			namespace,
299			def,
300		}))
301	}
302
303	pub fn name(&self) -> &str {
304		&self.0.def.name
305	}
306
307	pub fn def(&self) -> &Series {
308		&self.0.def
309	}
310
311	pub fn namespace(&self) -> &ResolvedNamespace {
312		&self.0.namespace
313	}
314
315	pub fn identifier(&self) -> &Fragment {
316		&self.0.identifier
317	}
318
319	pub fn fully_qualified_name(&self) -> String {
320		format!("{}.{}", self.0.namespace.name(), self.name())
321	}
322
323	pub fn columns(&self) -> &[Column] {
324		&self.0.def.columns
325	}
326
327	pub fn find_column(&self, name: &str) -> Option<&Column> {
328		self.0.def.columns.iter().find(|c| c.name == name)
329	}
330
331	pub fn to_static(&self) -> ResolvedSeries {
332		ResolvedSeries(Arc::new(ResolvedSeriesInner {
333			identifier: Fragment::internal(self.0.identifier.text()),
334			namespace: self.0.namespace.clone(),
335			def: self.0.def.clone(),
336		}))
337	}
338}
339
340#[derive(Debug, Clone)]
341pub struct ResolvedView(Arc<ResolvedViewInner>);
342
343#[derive(Debug)]
344struct ResolvedViewInner {
345	pub identifier: Fragment,
346	pub namespace: ResolvedNamespace,
347	pub def: View,
348}
349
350impl ResolvedView {
351	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, def: View) -> Self {
352		Self(Arc::new(ResolvedViewInner {
353			identifier,
354			namespace,
355			def,
356		}))
357	}
358
359	pub fn name(&self) -> &str {
360		self.0.def.name()
361	}
362
363	pub fn def(&self) -> &View {
364		&self.0.def
365	}
366
367	pub fn namespace(&self) -> &ResolvedNamespace {
368		&self.0.namespace
369	}
370
371	pub fn identifier(&self) -> &Fragment {
372		&self.0.identifier
373	}
374
375	pub fn columns(&self) -> &[Column] {
376		self.0.def.columns()
377	}
378
379	pub fn fully_qualified_name(&self) -> String {
380		format!("{}::{}", self.0.namespace.name(), self.name())
381	}
382
383	pub fn to_static(&self) -> ResolvedView {
384		ResolvedView(Arc::new(ResolvedViewInner {
385			identifier: Fragment::internal(self.0.identifier.text()),
386			namespace: self.0.namespace.clone(),
387			def: self.0.def.clone(),
388		}))
389	}
390}
391
392#[derive(Debug, Clone)]
393pub struct ResolvedDeferredView(Arc<ResolvedDeferredViewInner>);
394
395#[derive(Debug)]
396struct ResolvedDeferredViewInner {
397	pub identifier: Fragment,
398	pub namespace: ResolvedNamespace,
399	pub def: View,
400}
401
402impl ResolvedDeferredView {
403	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, def: View) -> Self {
404		Self(Arc::new(ResolvedDeferredViewInner {
405			identifier,
406			namespace,
407			def,
408		}))
409	}
410
411	pub fn name(&self) -> &str {
412		self.0.def.name()
413	}
414
415	pub fn def(&self) -> &View {
416		&self.0.def
417	}
418
419	pub fn namespace(&self) -> &ResolvedNamespace {
420		&self.0.namespace
421	}
422
423	pub fn identifier(&self) -> &Fragment {
424		&self.0.identifier
425	}
426
427	pub fn columns(&self) -> &[Column] {
428		self.0.def.columns()
429	}
430
431	pub fn to_static(&self) -> ResolvedDeferredView {
432		ResolvedDeferredView(Arc::new(ResolvedDeferredViewInner {
433			identifier: Fragment::internal(self.0.identifier.text()),
434			namespace: self.0.namespace.clone(),
435			def: self.0.def.clone(),
436		}))
437	}
438}
439
440#[derive(Debug, Clone)]
441pub struct ResolvedTransactionalView(Arc<ResolvedTransactionalViewInner>);
442
443#[derive(Debug)]
444struct ResolvedTransactionalViewInner {
445	pub identifier: Fragment,
446	pub namespace: ResolvedNamespace,
447	pub def: View,
448}
449
450impl ResolvedTransactionalView {
451	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, def: View) -> Self {
452		Self(Arc::new(ResolvedTransactionalViewInner {
453			identifier,
454			namespace,
455			def,
456		}))
457	}
458
459	pub fn name(&self) -> &str {
460		self.0.def.name()
461	}
462
463	pub fn def(&self) -> &View {
464		&self.0.def
465	}
466
467	pub fn namespace(&self) -> &ResolvedNamespace {
468		&self.0.namespace
469	}
470
471	pub fn identifier(&self) -> &Fragment {
472		&self.0.identifier
473	}
474
475	pub fn columns(&self) -> &[Column] {
476		self.0.def.columns()
477	}
478
479	pub fn to_static(&self) -> ResolvedTransactionalView {
480		ResolvedTransactionalView(Arc::new(ResolvedTransactionalViewInner {
481			identifier: Fragment::internal(self.0.identifier.text()),
482			namespace: self.0.namespace.clone(),
483			def: self.0.def.clone(),
484		}))
485	}
486}
487
488#[derive(Debug, Clone)]
489pub struct ResolvedSequence(Arc<ResolvedSequenceInner>);
490
491#[derive(Debug)]
492struct ResolvedSequenceInner {
493	pub identifier: Fragment,
494	pub namespace: ResolvedNamespace,
495	pub def: Sequence,
496}
497
498impl ResolvedSequence {
499	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, def: Sequence) -> Self {
500		Self(Arc::new(ResolvedSequenceInner {
501			identifier,
502			namespace,
503			def,
504		}))
505	}
506
507	pub fn identifier(&self) -> &Fragment {
508		&self.0.identifier
509	}
510
511	pub fn namespace(&self) -> &ResolvedNamespace {
512		&self.0.namespace
513	}
514
515	pub fn def(&self) -> &Sequence {
516		&self.0.def
517	}
518}
519
520#[derive(Debug, Clone)]
521pub struct ResolvedIndex(Arc<ResolvedIndexInner>);
522
523#[derive(Debug)]
524struct ResolvedIndexInner {
525	pub identifier: Fragment,
526	pub table: ResolvedTable,
527	pub def: Index,
528}
529
530impl ResolvedIndex {
531	pub fn new(identifier: Fragment, table: ResolvedTable, def: Index) -> Self {
532		Self(Arc::new(ResolvedIndexInner {
533			identifier,
534			table,
535			def,
536		}))
537	}
538
539	pub fn identifier(&self) -> &Fragment {
540		&self.0.identifier
541	}
542
543	pub fn table(&self) -> &ResolvedTable {
544		&self.0.table
545	}
546
547	pub fn def(&self) -> &Index {
548		&self.0.def
549	}
550}
551
552#[derive(Debug, Clone)]
553pub struct ResolvedFunction(Arc<ResolvedFunctionInner>);
554
555#[derive(Debug)]
556struct ResolvedFunctionInner {
557	pub identifier: Fragment,
558	pub namespace: Vec<ResolvedNamespace>,
559	pub def: Function,
560}
561
562impl ResolvedFunction {
563	pub fn new(identifier: Fragment, namespace: Vec<ResolvedNamespace>, def: Function) -> Self {
564		Self(Arc::new(ResolvedFunctionInner {
565			identifier,
566			namespace,
567			def,
568		}))
569	}
570
571	pub fn identifier(&self) -> &Fragment {
572		&self.0.identifier
573	}
574
575	pub fn namespace(&self) -> &[ResolvedNamespace] {
576		&self.0.namespace
577	}
578
579	pub fn def(&self) -> &Function {
580		&self.0.def
581	}
582}
583
584#[derive(Debug, Clone)]
585pub enum ResolvedShape {
586	Table(ResolvedTable),
587	TableVirtual(ResolvedTableVirtual),
588	View(ResolvedView),
589	DeferredView(ResolvedDeferredView),
590	TransactionalView(ResolvedTransactionalView),
591	RingBuffer(ResolvedRingBuffer),
592	Dictionary(ResolvedDictionary),
593	Series(ResolvedSeries),
594}
595
596impl ResolvedShape {
597	pub fn identifier(&self) -> &Fragment {
598		match self {
599			Self::Table(t) => t.identifier(),
600			Self::TableVirtual(t) => t.identifier(),
601			Self::View(v) => v.identifier(),
602			Self::DeferredView(v) => v.identifier(),
603			Self::TransactionalView(v) => v.identifier(),
604			Self::RingBuffer(r) => r.identifier(),
605			Self::Dictionary(d) => d.identifier(),
606			Self::Series(s) => s.identifier(),
607		}
608	}
609
610	pub fn name(&self) -> &str {
611		match self {
612			Self::Table(t) => t.name(),
613			Self::TableVirtual(t) => t.name(),
614			Self::View(v) => v.name(),
615			Self::DeferredView(v) => v.name(),
616			Self::TransactionalView(v) => v.name(),
617			Self::RingBuffer(r) => r.name(),
618			Self::Dictionary(d) => d.name(),
619			Self::Series(s) => s.name(),
620		}
621	}
622
623	pub fn namespace(&self) -> Option<&ResolvedNamespace> {
624		match self {
625			Self::Table(t) => Some(t.namespace()),
626			Self::TableVirtual(t) => Some(t.namespace()),
627			Self::View(v) => Some(v.namespace()),
628			Self::DeferredView(v) => Some(v.namespace()),
629			Self::TransactionalView(v) => Some(v.namespace()),
630			Self::RingBuffer(r) => Some(r.namespace()),
631			Self::Dictionary(d) => Some(d.namespace()),
632			Self::Series(s) => Some(s.namespace()),
633		}
634	}
635
636	pub fn supports_indexes(&self) -> bool {
637		matches!(self, Self::Table(_))
638	}
639
640	pub fn supports_mutations(&self) -> bool {
641		matches!(self, Self::Table(_) | Self::RingBuffer(_) | Self::Series(_))
642	}
643
644	pub fn columns(&self) -> &[Column] {
645		match self {
646			Self::Table(t) => t.columns(),
647			Self::TableVirtual(t) => t.columns(),
648			Self::View(v) => v.columns(),
649			Self::DeferredView(v) => v.columns(),
650			Self::TransactionalView(v) => v.columns(),
651			Self::RingBuffer(r) => r.columns(),
652			Self::Dictionary(_d) => unreachable!(),
653			Self::Series(s) => s.columns(),
654		}
655	}
656
657	pub fn find_column(&self, name: &str) -> Option<&Column> {
658		self.columns().iter().find(|c| c.name == name)
659	}
660
661	pub fn kind_name(&self) -> &'static str {
662		match self {
663			Self::Table(_) => "table",
664			Self::TableVirtual(_) => "virtual table",
665			Self::View(_) => "view",
666			Self::DeferredView(_) => "deferred view",
667			Self::TransactionalView(_) => "transactional view",
668			Self::RingBuffer(_) => "ring buffer",
669			Self::Dictionary(_) => "dictionary",
670			Self::Series(_) => "series",
671		}
672	}
673
674	pub fn fully_qualified_name(&self) -> Option<String> {
675		match self {
676			Self::Table(t) => Some(t.fully_qualified_name()),
677			Self::View(v) => Some(v.fully_qualified_name()),
678			Self::DeferredView(v) => Some(format!("{}::{}", v.namespace().name(), v.name())),
679			Self::TransactionalView(v) => Some(format!("{}::{}", v.namespace().name(), v.name())),
680			Self::TableVirtual(t) => Some(format!("{}::{}", t.namespace().name(), t.name())),
681			Self::RingBuffer(r) => Some(r.fully_qualified_name()),
682			Self::Dictionary(d) => Some(d.fully_qualified_name()),
683			Self::Series(s) => Some(s.fully_qualified_name()),
684		}
685	}
686
687	pub fn as_table(&self) -> Option<&ResolvedTable> {
688		match self {
689			Self::Table(t) => Some(t),
690			_ => None,
691		}
692	}
693
694	pub fn as_view(&self) -> Option<&ResolvedView> {
695		match self {
696			Self::View(v) => Some(v),
697			_ => None,
698		}
699	}
700
701	pub fn as_ringbuffer(&self) -> Option<&ResolvedRingBuffer> {
702		match self {
703			Self::RingBuffer(r) => Some(r),
704			_ => None,
705		}
706	}
707
708	pub fn as_dictionary(&self) -> Option<&ResolvedDictionary> {
709		match self {
710			Self::Dictionary(d) => Some(d),
711			_ => None,
712		}
713	}
714
715	pub fn as_series(&self) -> Option<&ResolvedSeries> {
716		match self {
717			Self::Series(s) => Some(s),
718			_ => None,
719		}
720	}
721}
722
723#[derive(Debug, Clone)]
724pub struct ResolvedColumn(Arc<ResolvedColumnInner>);
725
726#[derive(Debug)]
727struct ResolvedColumnInner {
728	pub identifier: Fragment,
729
730	pub shape: ResolvedShape,
731
732	pub def: Column,
733}
734
735impl ResolvedColumn {
736	pub fn new(identifier: Fragment, shape: ResolvedShape, def: Column) -> Self {
737		Self(Arc::new(ResolvedColumnInner {
738			identifier,
739			shape,
740			def,
741		}))
742	}
743
744	pub fn name(&self) -> &str {
745		&self.0.def.name
746	}
747
748	pub fn def(&self) -> &Column {
749		&self.0.def
750	}
751
752	pub fn identifier(&self) -> &Fragment {
753		&self.0.identifier
754	}
755
756	pub fn shape(&self) -> &ResolvedShape {
757		&self.0.shape
758	}
759
760	pub fn type_constraint(&self) -> &TypeConstraint {
761		&self.0.def.constraint
762	}
763
764	pub fn column_type(&self) -> Type {
765		self.0.def.constraint.get_type()
766	}
767
768	pub fn properties(&self) -> Vec<ColumnPropertyKind> {
769		self.0.def.properties.iter().map(|p| p.property.clone()).collect()
770	}
771
772	pub fn is_auto_increment(&self) -> bool {
773		self.0.def.auto_increment
774	}
775
776	pub fn namespace(&self) -> Option<&ResolvedNamespace> {
777		self.0.shape.namespace()
778	}
779
780	pub fn qualified_name(&self) -> String {
781		match self.0.shape.fully_qualified_name() {
782			Some(shape_name) => {
783				format!("{}.{}", shape_name, self.name())
784			}
785			None => format!("{}.{}", self.0.shape.identifier().text(), self.name()),
786		}
787	}
788
789	pub fn fragment(&self) -> &Fragment {
790		&self.0.identifier
791	}
792
793	pub fn to_static(&self) -> ResolvedColumn {
794		ResolvedColumn(Arc::new(ResolvedColumnInner {
795			identifier: Fragment::internal(self.0.identifier.text()),
796			shape: self.0.shape.clone(),
797			def: self.0.def.clone(),
798		}))
799	}
800}
801
802pub fn resolved_column_to_number_descriptor(column: &ResolvedColumn) -> NumberOutOfRangeDescriptor {
803	let (namespace, table) = match column.shape() {
804		ResolvedShape::Table(table) => {
805			(Some(table.namespace().name().to_string()), Some(table.name().to_string()))
806		}
807		ResolvedShape::TableVirtual(table) => {
808			(Some(table.namespace().name().to_string()), Some(table.name().to_string()))
809		}
810		ResolvedShape::RingBuffer(rb) => (Some(rb.namespace().name().to_string()), Some(rb.name().to_string())),
811		ResolvedShape::View(view) => (Some(view.namespace().name().to_string()), Some(view.name().to_string())),
812		ResolvedShape::DeferredView(view) => {
813			(Some(view.namespace().name().to_string()), Some(view.name().to_string()))
814		}
815		ResolvedShape::TransactionalView(view) => {
816			(Some(view.namespace().name().to_string()), Some(view.name().to_string()))
817		}
818		ResolvedShape::Dictionary(dict) => {
819			(Some(dict.namespace().name().to_string()), Some(dict.name().to_string()))
820		}
821		ResolvedShape::Series(series) => {
822			(Some(series.namespace().name().to_string()), Some(series.name().to_string()))
823		}
824	};
825
826	NumberOutOfRangeDescriptor {
827		namespace,
828		table,
829		column: Some(column.name().to_string()),
830		column_type: Some(column.column_type()),
831	}
832}
833
834#[derive(Debug, Clone, Serialize, Deserialize)]
835pub struct Sequence {
836	pub name: String,
837	pub current_value: i64,
838	pub increment: i64,
839}
840
841#[derive(Debug, Clone, Serialize, Deserialize)]
842pub struct Index {
843	pub name: String,
844	pub columns: Vec<String>,
845	pub unique: bool,
846}
847
848#[derive(Debug, Clone, Serialize, Deserialize)]
849pub struct Function {
850	pub name: String,
851	pub parameters: Vec<String>,
852	pub return_type: String,
853}
854
855#[cfg(test)]
856pub mod tests {
857	use reifydb_type::{
858		fragment::Fragment,
859		value::{constraint::TypeConstraint, r#type::Type},
860	};
861
862	use super::*;
863	use crate::interface::catalog::{
864		column::ColumnIndex,
865		id::{ColumnId, NamespaceId, TableId},
866	};
867
868	fn test_namespace_def() -> Namespace {
869		Namespace::Local {
870			id: NamespaceId::SYSTEM,
871			name: "public".to_string(),
872			local_name: "public".to_string(),
873			parent_id: NamespaceId::ROOT,
874		}
875	}
876
877	fn test_table() -> Table {
878		Table {
879			id: TableId(1),
880			namespace: NamespaceId::SYSTEM,
881			name: "users".to_string(),
882			columns: vec![
883				Column {
884					id: ColumnId(1),
885					name: "id".to_string(),
886					constraint: TypeConstraint::unconstrained(Type::Int8),
887					properties: vec![],
888					index: ColumnIndex(0),
889					auto_increment: false,
890					dictionary_id: None,
891				},
892				Column {
893					id: ColumnId(2),
894					name: "name".to_string(),
895					constraint: TypeConstraint::unconstrained(Type::Utf8),
896					properties: vec![],
897					index: ColumnIndex(1),
898					auto_increment: false,
899					dictionary_id: None,
900				},
901			],
902			primary_key: None,
903			underlying: false,
904		}
905	}
906
907	#[test]
908	fn test_resolved_namespace() {
909		let identifier = Fragment::testing("public");
910		let def = test_namespace_def();
911		let resolved = ResolvedNamespace::new(identifier, def);
912
913		assert_eq!(resolved.name(), "public");
914		assert_eq!(resolved.fragment().text(), "public");
915	}
916
917	#[test]
918	fn test_resolved_table() {
919		let namespace_ident = Fragment::testing("public");
920		let namespace = ResolvedNamespace::new(namespace_ident, test_namespace_def());
921
922		let table_ident = Fragment::testing("users");
923		let table = ResolvedTable::new(table_ident, namespace.clone(), test_table());
924
925		assert_eq!(table.name(), "users");
926		assert_eq!(table.fully_qualified_name(), "public::users");
927		assert_eq!(table.columns().len(), 2);
928		assert!(table.find_column("id").is_some());
929		assert!(table.find_column("nonexistent").is_none());
930	}
931
932	#[test]
933	fn test_resolved_shape_enum() {
934		let namespace = ResolvedNamespace::new(Fragment::testing("public"), test_namespace_def());
935
936		let table = ResolvedTable::new(Fragment::testing("users"), namespace, test_table());
937
938		let shape = ResolvedShape::Table(table);
939
940		assert!(shape.supports_indexes());
941		assert!(shape.supports_mutations());
942		assert_eq!(shape.kind_name(), "table");
943		// effective_name removed - use identifier().text() instead
944		assert_eq!(shape.fully_qualified_name(), Some("public::users".to_string()));
945		assert!(shape.as_table().is_some());
946		assert!(shape.as_view().is_none());
947	}
948
949	#[test]
950	fn test_resolved_column() {
951		let namespace = ResolvedNamespace::new(Fragment::testing("public"), test_namespace_def());
952
953		let table = ResolvedTable::new(Fragment::testing("users"), namespace, test_table());
954
955		let shape = ResolvedShape::Table(table);
956
957		let column_ident = Fragment::testing("id");
958
959		let column = Column {
960			id: ColumnId(1),
961			name: "id".to_string(),
962			constraint: TypeConstraint::unconstrained(Type::Int8),
963			properties: vec![],
964			index: ColumnIndex(0),
965			auto_increment: false,
966			dictionary_id: None,
967		};
968
969		let column = ResolvedColumn::new(column_ident, shape, column);
970
971		assert_eq!(column.name(), "id");
972		assert_eq!(column.type_constraint(), &TypeConstraint::unconstrained(Type::Int8));
973		assert!(!column.is_auto_increment());
974		assert_eq!(column.qualified_name(), "public::users.id");
975	}
976}