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