Skip to main content

reifydb_core/interface/
resolved.rs

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