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(Arc<ResolvedNamespaceInner>);
17
18#[derive(Debug)]
19struct ResolvedNamespaceInner {
20	pub identifier: Fragment,
21	pub def: NamespaceDef,
22}
23
24impl ResolvedNamespace {
25	pub fn new(identifier: Fragment, 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 {
44		&self.0.identifier
45	}
46
47	/// Convert to owned version with 'static lifetime
48	pub fn to_static(&self) -> ResolvedNamespace {
49		ResolvedNamespace(Arc::new(ResolvedNamespaceInner {
50			identifier: Fragment::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(Arc<ResolvedTableInner>);
59
60#[derive(Debug)]
61struct ResolvedTableInner {
62	pub identifier: Fragment,
63	pub namespace: ResolvedNamespace,
64	pub def: TableDef,
65}
66
67impl ResolvedTable {
68	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, 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 {
88		&self.0.namespace
89	}
90
91	/// Get the identifier
92	pub fn identifier(&self) -> &Fragment {
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 {
113		ResolvedTable(Arc::new(ResolvedTableInner {
114			identifier: Fragment::internal(self.0.identifier.text()),
115			namespace: self.0.namespace.clone(),
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(Arc<ResolvedTableVirtualInner>);
124
125#[derive(Debug)]
126struct ResolvedTableVirtualInner {
127	pub identifier: Fragment,
128	pub namespace: ResolvedNamespace,
129	pub def: TableVirtualDef,
130}
131
132impl ResolvedTableVirtual {
133	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, 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 {
150		&self.0.namespace
151	}
152
153	pub fn identifier(&self) -> &Fragment {
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 {
163		ResolvedTableVirtual(Arc::new(ResolvedTableVirtualInner {
164			identifier: Fragment::internal(self.0.identifier.text()),
165			namespace: self.0.namespace.clone(),
166			def: self.0.def.clone(),
167		}))
168	}
169}
170
171/// Resolved ring buffer
172#[derive(Debug, Clone)]
173pub struct ResolvedRingBuffer(Arc<ResolvedRingBufferInner>);
174
175#[derive(Debug)]
176struct ResolvedRingBufferInner {
177	pub identifier: Fragment,
178	pub namespace: ResolvedNamespace,
179	pub def: RingBufferDef,
180}
181
182impl ResolvedRingBuffer {
183	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, 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 {
203		&self.0.namespace
204	}
205
206	/// Get the identifier
207	pub fn identifier(&self) -> &Fragment {
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 {
228		ResolvedRingBuffer(Arc::new(ResolvedRingBufferInner {
229			identifier: Fragment::internal(self.0.identifier.text()),
230			namespace: self.0.namespace.clone(),
231			def: self.0.def.clone(),
232		}))
233	}
234}
235
236/// Resolved flow
237#[derive(Debug, Clone)]
238pub struct ResolvedFlow(Arc<ResolvedFlowInner>);
239
240#[derive(Debug)]
241struct ResolvedFlowInner {
242	pub identifier: Fragment,
243	pub namespace: ResolvedNamespace,
244	pub def: FlowDef,
245}
246
247impl ResolvedFlow {
248	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, 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 {
268		&self.0.namespace
269	}
270
271	/// Get the identifier
272	pub fn identifier(&self) -> &Fragment {
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 {
283		ResolvedFlow(Arc::new(ResolvedFlowInner {
284			identifier: Fragment::internal(self.0.identifier.text()),
285			namespace: self.0.namespace.clone(),
286			def: self.0.def.clone(),
287		}))
288	}
289}
290
291/// Resolved dictionary
292#[derive(Debug, Clone)]
293pub struct ResolvedDictionary(Arc<ResolvedDictionaryInner>);
294
295#[derive(Debug)]
296struct ResolvedDictionaryInner {
297	pub identifier: Fragment,
298	pub namespace: ResolvedNamespace,
299	pub def: DictionaryDef,
300}
301
302impl ResolvedDictionary {
303	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, 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 {
323		&self.0.namespace
324	}
325
326	/// Get the identifier
327	pub fn identifier(&self) -> &Fragment {
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 {
338		ResolvedDictionary(Arc::new(ResolvedDictionaryInner {
339			identifier: Fragment::internal(self.0.identifier.text()),
340			namespace: self.0.namespace.clone(),
341			def: self.0.def.clone(),
342		}))
343	}
344}
345
346/// Resolved standard view
347#[derive(Debug, Clone)]
348pub struct ResolvedView(Arc<ResolvedViewInner>);
349
350#[derive(Debug)]
351struct ResolvedViewInner {
352	pub identifier: Fragment,
353	pub namespace: ResolvedNamespace,
354	pub def: ViewDef,
355}
356
357impl ResolvedView {
358	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, 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 {
375		&self.0.namespace
376	}
377
378	pub fn identifier(&self) -> &Fragment {
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 {
392		ResolvedView(Arc::new(ResolvedViewInner {
393			identifier: Fragment::internal(self.0.identifier.text()),
394			namespace: self.0.namespace.clone(),
395			def: self.0.def.clone(),
396		}))
397	}
398}
399
400#[derive(Debug, Clone)]
401pub struct ResolvedDeferredView(Arc<ResolvedDeferredViewInner>);
402
403#[derive(Debug)]
404struct ResolvedDeferredViewInner {
405	pub identifier: Fragment,
406	pub namespace: ResolvedNamespace,
407	pub def: ViewDef,
408}
409
410impl ResolvedDeferredView {
411	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, 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 {
428		&self.0.namespace
429	}
430
431	pub fn identifier(&self) -> &Fragment {
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 {
441		ResolvedDeferredView(Arc::new(ResolvedDeferredViewInner {
442			identifier: Fragment::internal(self.0.identifier.text()),
443			namespace: self.0.namespace.clone(),
444			def: self.0.def.clone(),
445		}))
446	}
447}
448
449#[derive(Debug, Clone)]
450pub struct ResolvedTransactionalView(Arc<ResolvedTransactionalViewInner>);
451
452#[derive(Debug)]
453struct ResolvedTransactionalViewInner {
454	pub identifier: Fragment,
455	pub namespace: ResolvedNamespace,
456	pub def: ViewDef,
457}
458
459impl ResolvedTransactionalView {
460	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, 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 {
477		&self.0.namespace
478	}
479
480	pub fn identifier(&self) -> &Fragment {
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 {
490		ResolvedTransactionalView(Arc::new(ResolvedTransactionalViewInner {
491			identifier: Fragment::internal(self.0.identifier.text()),
492			namespace: self.0.namespace.clone(),
493			def: self.0.def.clone(),
494		}))
495	}
496}
497
498#[derive(Debug, Clone)]
499pub struct ResolvedSequence(Arc<ResolvedSequenceInner>);
500
501#[derive(Debug)]
502struct ResolvedSequenceInner {
503	pub identifier: Fragment,
504	pub namespace: ResolvedNamespace,
505	pub def: SequenceDef,
506}
507
508impl ResolvedSequence {
509	pub fn new(identifier: Fragment, namespace: ResolvedNamespace, def: SequenceDef) -> Self {
510		Self(Arc::new(ResolvedSequenceInner {
511			identifier,
512			namespace,
513			def,
514		}))
515	}
516
517	pub fn identifier(&self) -> &Fragment {
518		&self.0.identifier
519	}
520
521	pub fn namespace(&self) -> &ResolvedNamespace {
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(Arc<ResolvedIndexInner>);
532
533#[derive(Debug)]
534struct ResolvedIndexInner {
535	pub identifier: Fragment,
536	pub table: ResolvedTable,
537	pub def: IndexDef,
538}
539
540impl ResolvedIndex {
541	pub fn new(identifier: Fragment, table: ResolvedTable, def: IndexDef) -> Self {
542		Self(Arc::new(ResolvedIndexInner {
543			identifier,
544			table,
545			def,
546		}))
547	}
548
549	pub fn identifier(&self) -> &Fragment {
550		&self.0.identifier
551	}
552
553	pub fn table(&self) -> &ResolvedTable {
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(Arc<ResolvedFunctionInner>);
564
565#[derive(Debug)]
566struct ResolvedFunctionInner {
567	pub identifier: Fragment,
568	pub namespace: Vec<ResolvedNamespace>,
569	pub def: FunctionDef,
570}
571
572impl ResolvedFunction {
573	pub fn new(identifier: Fragment, namespace: Vec<ResolvedNamespace>, def: FunctionDef) -> Self {
574		Self(Arc::new(ResolvedFunctionInner {
575			identifier,
576			namespace,
577			def,
578		}))
579	}
580
581	pub fn identifier(&self) -> &Fragment {
582		&self.0.identifier
583	}
584
585	pub fn namespace(&self) -> &[ResolvedNamespace] {
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 {
596	Table(ResolvedTable),
597	TableVirtual(ResolvedTableVirtual),
598	View(ResolvedView),
599	DeferredView(ResolvedDeferredView),
600	TransactionalView(ResolvedTransactionalView),
601	RingBuffer(ResolvedRingBuffer),
602	Flow(ResolvedFlow),
603	Dictionary(ResolvedDictionary),
604}
605
606impl ResolvedSource {
607	/// Get the identifier fragment
608	pub fn identifier(&self) -> &Fragment {
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> {
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> {
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> {
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_ringbuffer(&self) -> Option<&ResolvedRingBuffer> {
710		match self {
711			Self::RingBuffer(r) => Some(r),
712			_ => None,
713		}
714	}
715
716	/// Convert to a dictionary if this is a dictionary source
717	pub fn as_dictionary(&self) -> Option<&ResolvedDictionary> {
718		match self {
719			Self::Dictionary(d) => Some(d),
720			_ => None,
721		}
722	}
723}
724
725/// Column with its resolved source
726#[derive(Debug, Clone)]
727pub struct ResolvedColumn(Arc<ResolvedColumnInner>);
728
729#[derive(Debug)]
730struct ResolvedColumnInner {
731	/// Original identifier with fragments
732	pub identifier: Fragment,
733	/// The resolved source this column belongs to
734	pub source: ResolvedSource,
735	/// The column definition
736	pub def: ColumnDef,
737}
738
739impl ResolvedColumn {
740	pub fn new(identifier: Fragment, source: ResolvedSource, def: ColumnDef) -> Self {
741		Self(Arc::new(ResolvedColumnInner {
742			identifier,
743			source,
744			def,
745		}))
746	}
747
748	/// Get the column name
749	pub fn name(&self) -> &str {
750		&self.0.def.name
751	}
752
753	/// Get the column def
754	pub fn def(&self) -> &ColumnDef {
755		&self.0.def
756	}
757
758	/// Get the identifier
759	pub fn identifier(&self) -> &Fragment {
760		&self.0.identifier
761	}
762
763	/// Get the source
764	pub fn source(&self) -> &ResolvedSource {
765		&self.0.source
766	}
767
768	/// Get the type constraint of this column
769	pub fn type_constraint(&self) -> &TypeConstraint {
770		&self.0.def.constraint
771	}
772
773	/// Get the column type
774	pub fn column_type(&self) -> Type {
775		self.0.def.constraint.get_type()
776	}
777
778	/// Get the column policies
779	pub fn policies(&self) -> Vec<ColumnPolicyKind> {
780		self.0.def.policies.iter().map(|p| p.policy.clone()).collect()
781	}
782
783	/// Check if column has auto increment
784	pub fn is_auto_increment(&self) -> bool {
785		self.0.def.auto_increment
786	}
787
788	/// Get the namespace this column belongs to
789	pub fn namespace(&self) -> Option<&ResolvedNamespace> {
790		self.0.source.namespace()
791	}
792
793	/// Get fully qualified name
794	pub fn qualified_name(&self) -> String {
795		match self.0.source.fully_qualified_name() {
796			Some(source_name) => {
797				format!("{}.{}", source_name, self.name())
798			}
799			None => format!("{}.{}", self.0.source.identifier().text(), self.name()),
800		}
801	}
802
803	/// Get the fragment for error reporting
804	pub fn fragment(&self) -> &Fragment {
805		&self.0.identifier
806	}
807
808	/// Convert to owned version with 'static lifetime
809	pub fn to_static(&self) -> ResolvedColumn {
810		ResolvedColumn(Arc::new(ResolvedColumnInner {
811			identifier: Fragment::internal(self.0.identifier.text()),
812			source: self.0.source.clone(),
813			def: self.0.def.clone(),
814		}))
815	}
816}
817
818// Helper function to convert ResolvedColumn to NumberOfRangeColumnDescriptor
819// This is used in evaluation context for error reporting
820pub fn resolved_column_to_number_descriptor(column: &ResolvedColumn) -> NumberOfRangeColumnDescriptor<'_> {
821	let (namespace, table) = match column.source() {
822		ResolvedSource::Table(table) => (Some(table.namespace().name().as_ref()), Some(table.name().as_ref())),
823		ResolvedSource::TableVirtual(table) => {
824			(Some(table.namespace().name().as_ref()), Some(table.name().as_ref()))
825		}
826		ResolvedSource::RingBuffer(rb) => (Some(rb.namespace().name().as_ref()), Some(rb.name().as_ref())),
827		ResolvedSource::View(view) => (Some(view.namespace().name().as_ref()), Some(view.name().as_ref())),
828		ResolvedSource::DeferredView(view) => {
829			(Some(view.namespace().name().as_ref()), Some(view.name().as_ref()))
830		}
831		ResolvedSource::TransactionalView(view) => {
832			(Some(view.namespace().name().as_ref()), Some(view.name().as_ref()))
833		}
834		ResolvedSource::Flow(flow) => (Some(flow.namespace().name().as_ref()), Some(flow.name().as_ref())),
835		ResolvedSource::Dictionary(dict) => {
836			(Some(dict.namespace().name().as_ref()), Some(dict.name().as_ref()))
837		}
838	};
839
840	let mut descriptor = NumberOfRangeColumnDescriptor::new();
841	if let Some(ns) = namespace {
842		descriptor = descriptor.with_namespace(ns);
843	}
844	if let Some(tbl) = table {
845		descriptor = descriptor.with_table(tbl);
846	}
847	descriptor.with_column(column.name().as_ref()).with_column_type(column.column_type())
848}
849
850// Placeholder types - these will be defined properly in catalog
851#[derive(Debug, Clone, Serialize, Deserialize)]
852pub struct SequenceDef {
853	pub name: String,
854	pub current_value: i64,
855	pub increment: i64,
856}
857
858#[derive(Debug, Clone, Serialize, Deserialize)]
859pub struct IndexDef {
860	pub name: String,
861	pub columns: Vec<String>,
862	pub unique: bool,
863}
864
865#[derive(Debug, Clone, Serialize, Deserialize)]
866pub struct FunctionDef {
867	pub name: String,
868	pub parameters: Vec<String>,
869	pub return_type: String,
870}
871
872#[cfg(test)]
873mod tests {
874	use reifydb_type::{Type, fragment::Fragment};
875
876	use super::*;
877	use crate::interface::{ColumnId, NamespaceId, TableId, catalog::ColumnIndex};
878
879	fn test_namespace_def() -> NamespaceDef {
880		NamespaceDef {
881			id: NamespaceId(1),
882			name: "public".to_string(),
883		}
884	}
885
886	fn test_table_def() -> TableDef {
887		TableDef {
888			id: TableId(1),
889			namespace: NamespaceId(1),
890			name: "users".to_string(),
891			columns: vec![
892				ColumnDef {
893					id: ColumnId(1),
894					name: "id".to_string(),
895					constraint: TypeConstraint::unconstrained(Type::Int8),
896					policies: vec![],
897					index: ColumnIndex(0),
898					auto_increment: false,
899					dictionary_id: None,
900				},
901				ColumnDef {
902					id: ColumnId(2),
903					name: "name".to_string(),
904					constraint: TypeConstraint::unconstrained(Type::Utf8),
905					policies: vec![],
906					index: ColumnIndex(1),
907					auto_increment: false,
908					dictionary_id: None,
909				},
910			],
911			primary_key: None,
912		}
913	}
914
915	#[test]
916	fn test_resolved_namespace() {
917		let identifier = Fragment::testing("public");
918		let def = test_namespace_def();
919		let resolved = ResolvedNamespace::new(identifier, def);
920
921		assert_eq!(resolved.name(), "public");
922		assert_eq!(resolved.fragment().text(), "public");
923	}
924
925	#[test]
926	fn test_resolved_table() {
927		let namespace_ident = Fragment::testing("public");
928		let namespace = ResolvedNamespace::new(namespace_ident, test_namespace_def());
929
930		let table_ident = Fragment::testing("users");
931		let table = ResolvedTable::new(table_ident, namespace.clone(), test_table_def());
932
933		assert_eq!(table.name(), "users");
934		assert_eq!(table.fully_qualified_name(), "public.users");
935		assert_eq!(table.columns().len(), 2);
936		assert!(table.find_column("id").is_some());
937		assert!(table.find_column("nonexistent").is_none());
938	}
939
940	#[test]
941	fn test_resolved_source_enum() {
942		let namespace = ResolvedNamespace::new(Fragment::testing("public"), test_namespace_def());
943
944		let table = ResolvedTable::new(Fragment::testing("users"), namespace, test_table_def());
945
946		let source = ResolvedSource::Table(table);
947
948		assert!(source.supports_indexes());
949		assert!(source.supports_mutations());
950		assert_eq!(source.kind_name(), "table");
951		// effective_name removed - use identifier().text() instead
952		assert_eq!(source.fully_qualified_name(), Some("public.users".to_string()));
953		assert!(source.as_table().is_some());
954		assert!(source.as_view().is_none());
955	}
956
957	#[test]
958	fn test_resolved_column() {
959		let namespace = ResolvedNamespace::new(Fragment::testing("public"), test_namespace_def());
960
961		let table = ResolvedTable::new(Fragment::testing("users"), namespace, test_table_def());
962
963		let source = ResolvedSource::Table(table);
964
965		let column_ident = Fragment::testing("id");
966
967		let column_def = ColumnDef {
968			id: ColumnId(1),
969			name: "id".to_string(),
970			constraint: TypeConstraint::unconstrained(Type::Int8),
971			policies: vec![],
972			index: ColumnIndex(0),
973			auto_increment: false,
974			dictionary_id: None,
975		};
976
977		let column = ResolvedColumn::new(column_ident, source, column_def);
978
979		assert_eq!(column.name(), "id");
980		assert_eq!(column.type_constraint(), &TypeConstraint::unconstrained(Type::Int8));
981		assert!(!column.is_auto_increment());
982		assert_eq!(column.qualified_name(), "public.users.id");
983	}
984}