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