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