1use core::fmt;
9use std::any::TypeId;
10use std::collections::{btree_map, BTreeMap};
11
12use itertools::Itertools as _;
13use spacetimedb_primitives::{ColId, ColList};
14use spacetimedb_sats::typespace::TypespaceBuilder;
15use spacetimedb_sats::{AlgebraicType, AlgebraicTypeRef, AlgebraicValue, ProductType, SpacetimeType, Typespace};
16
17use crate::db::raw_def::v9::{Lifecycle, RawIdentifier, RawIndexAlgorithm, TableAccess, TableType};
18
19#[derive(Default, Debug, Clone, SpacetimeType)]
37#[sats(crate = crate)]
38#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
39pub struct RawModuleDefV10 {
40 pub sections: Vec<RawModuleDefV10Section>,
44}
45
46#[derive(Debug, Clone, SpacetimeType)]
50#[sats(crate = crate)]
51#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
52#[non_exhaustive]
53pub enum RawModuleDefV10Section {
54 Typespace(Typespace),
59
60 Types(Vec<RawTypeDefV10>),
62
63 Tables(Vec<RawTableDefV10>),
65
66 Reducers(Vec<RawReducerDefV10>),
68
69 Procedures(Vec<RawProcedureDefV10>),
71
72 Views(Vec<RawViewDefV10>),
74
75 Schedules(Vec<RawScheduleDefV10>),
80
81 LifeCycleReducers(Vec<RawLifeCycleReducerDefV10>),
86
87 RowLevelSecurity(Vec<RawRowLevelSecurityDefV10>), }
89
90pub type RawRowLevelSecurityDefV10 = crate::db::raw_def::v9::RawRowLevelSecurityDefV9;
91
92#[derive(Debug, Clone, SpacetimeType)]
101#[sats(crate = crate)]
102#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
103pub struct RawTableDefV10 {
104 pub source_name: RawIdentifier,
108
109 pub product_type_ref: AlgebraicTypeRef,
116
117 pub primary_key: ColList,
126
127 pub indexes: Vec<RawIndexDefV10>,
129
130 pub constraints: Vec<RawConstraintDefV10>,
132
133 pub sequences: Vec<RawSequenceDefV10>,
135
136 pub table_type: TableType,
138
139 pub table_access: TableAccess,
141
142 pub default_values: Vec<RawColumnDefaultValueV10>,
144}
145
146#[derive(Debug, Clone, SpacetimeType)]
148#[sats(crate = crate)]
149#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
150pub struct RawColumnDefaultValueV10 {
151 pub col_id: ColId,
153
154 pub value: Box<[u8]>,
157}
158
159#[derive(Debug, Clone, SpacetimeType)]
161#[sats(crate = crate)]
162#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
163pub struct RawReducerDefV10 {
164 pub source_name: RawIdentifier,
166
167 pub params: ProductType,
170
171 pub visibility: FunctionVisibility,
173
174 pub ok_return_type: AlgebraicType,
176
177 pub err_return_type: AlgebraicType,
179}
180
181#[derive(Debug, Copy, Clone, SpacetimeType)]
183#[sats(crate = crate)]
184#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
185pub enum FunctionVisibility {
186 Internal,
189
190 ClientCallable,
192}
193
194#[derive(Debug, Clone, SpacetimeType)]
196#[sats(crate = crate)]
197#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
198pub struct RawScheduleDefV10 {
199 pub source_name: Option<Box<str>>,
203
204 pub table_name: RawIdentifier,
206
207 pub schedule_at_col: ColId,
209
210 pub function_name: RawIdentifier,
212}
213
214#[derive(Debug, Clone, SpacetimeType)]
216#[sats(crate = crate)]
217#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
218pub struct RawLifeCycleReducerDefV10 {
219 pub lifecycle_spec: Lifecycle,
221
222 pub function_name: RawIdentifier,
224}
225
226#[derive(Debug, Clone, SpacetimeType)]
228#[sats(crate = crate)]
229#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
230pub struct RawProcedureDefV10 {
231 pub source_name: RawIdentifier,
233
234 pub params: ProductType,
237
238 pub return_type: AlgebraicType,
243
244 pub visibility: FunctionVisibility,
246}
247
248#[derive(Debug, Clone, SpacetimeType)]
250#[sats(crate = crate)]
251#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
252pub struct RawSequenceDefV10 {
253 pub source_name: Option<Box<str>>,
257
258 pub column: ColId,
263
264 pub start: Option<i128>,
268
269 pub min_value: Option<i128>,
272
273 pub max_value: Option<i128>,
276
277 pub increment: i128,
279}
280
281#[derive(Debug, Clone, SpacetimeType)]
283#[sats(crate = crate)]
284#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
285pub struct RawIndexDefV10 {
286 pub source_name: Option<Box<str>>,
289
290 pub accessor_name: Option<RawIdentifier>,
301
302 pub algorithm: RawIndexAlgorithm,
304}
305
306#[derive(Debug, Clone, SpacetimeType)]
308#[sats(crate = crate)]
309#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
310pub struct RawConstraintDefV10 {
311 pub source_name: Option<Box<str>>,
314
315 pub data: RawConstraintDataV10,
317}
318
319type RawConstraintDataV10 = crate::db::raw_def::v9::RawConstraintDataV9;
320type RawUniqueConstraintDataV10 = crate::db::raw_def::v9::RawUniqueConstraintDataV9;
321
322#[derive(Debug, Clone, SpacetimeType)]
326#[sats(crate = crate)]
327#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
328pub struct RawTypeDefV10 {
329 pub source_name: RawScopedTypeNameV10,
331
332 pub ty: AlgebraicTypeRef,
335
336 pub custom_ordering: bool,
338}
339
340#[derive(Clone, SpacetimeType, PartialEq, Eq, PartialOrd, Ord)]
345#[sats(crate = crate)]
346pub struct RawScopedTypeNameV10 {
347 pub scope: Box<[RawIdentifier]>,
352
353 pub source_name: RawIdentifier,
357}
358
359impl fmt::Debug for RawScopedTypeNameV10 {
360 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361 for module in self.scope.iter() {
362 fmt::Debug::fmt(module, f)?;
363 f.write_str("::")?;
364 }
365 fmt::Debug::fmt(&self.source_name, f)?;
366 Ok(())
367 }
368}
369
370#[derive(Debug, Clone, SpacetimeType)]
372#[sats(crate = crate)]
373#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
374pub struct RawViewDefV10 {
375 pub source_name: RawIdentifier,
377
378 pub index: u32,
380
381 pub is_public: bool,
385
386 pub is_anonymous: bool,
391
392 pub params: ProductType,
395
396 pub return_type: AlgebraicType,
406}
407
408impl RawModuleDefV10 {
409 pub fn types(&self) -> Option<&Vec<RawTypeDefV10>> {
411 self.sections.iter().find_map(|s| match s {
412 RawModuleDefV10Section::Types(types) => Some(types),
413 _ => None,
414 })
415 }
416
417 pub fn tables(&self) -> Option<&Vec<RawTableDefV10>> {
419 self.sections.iter().find_map(|s| match s {
420 RawModuleDefV10Section::Tables(tables) => Some(tables),
421 _ => None,
422 })
423 }
424
425 pub fn typespace(&self) -> Option<&Typespace> {
427 self.sections.iter().find_map(|s| match s {
428 RawModuleDefV10Section::Typespace(ts) => Some(ts),
429 _ => None,
430 })
431 }
432
433 pub fn reducers(&self) -> Option<&Vec<RawReducerDefV10>> {
435 self.sections.iter().find_map(|s| match s {
436 RawModuleDefV10Section::Reducers(reducers) => Some(reducers),
437 _ => None,
438 })
439 }
440
441 pub fn procedures(&self) -> Option<&Vec<RawProcedureDefV10>> {
443 self.sections.iter().find_map(|s| match s {
444 RawModuleDefV10Section::Procedures(procedures) => Some(procedures),
445 _ => None,
446 })
447 }
448
449 pub fn views(&self) -> Option<&Vec<RawViewDefV10>> {
451 self.sections.iter().find_map(|s| match s {
452 RawModuleDefV10Section::Views(views) => Some(views),
453 _ => None,
454 })
455 }
456
457 pub fn schedules(&self) -> Option<&Vec<RawScheduleDefV10>> {
459 self.sections.iter().find_map(|s| match s {
460 RawModuleDefV10Section::Schedules(schedules) => Some(schedules),
461 _ => None,
462 })
463 }
464
465 pub fn lifecycle_reducers(&self) -> Option<&Vec<RawLifeCycleReducerDefV10>> {
467 self.sections.iter().find_map(|s| match s {
468 RawModuleDefV10Section::LifeCycleReducers(lcrs) => Some(lcrs),
469 _ => None,
470 })
471 }
472
473 pub fn tables_mut_for_tests(&mut self) -> &mut Vec<RawTableDefV10> {
474 self.sections
475 .iter_mut()
476 .find_map(|s| match s {
477 RawModuleDefV10Section::Tables(tables) => Some(tables),
478 _ => None,
479 })
480 .expect("Tables section must exist for tests")
481 }
482
483 pub fn row_level_security(&self) -> Option<&Vec<RawRowLevelSecurityDefV10>> {
485 self.sections.iter().find_map(|s| match s {
486 RawModuleDefV10Section::RowLevelSecurity(rls) => Some(rls),
487 _ => None,
488 })
489 }
490}
491
492#[derive(Default)]
494pub struct RawModuleDefV10Builder {
495 module: RawModuleDefV10,
497
498 type_map: BTreeMap<TypeId, AlgebraicTypeRef>,
500}
501
502impl RawModuleDefV10Builder {
503 pub fn new() -> Self {
505 Default::default()
506 }
507
508 fn typespace_mut(&mut self) -> &mut Typespace {
510 let idx = self
511 .module
512 .sections
513 .iter()
514 .position(|s| matches!(s, RawModuleDefV10Section::Typespace(_)))
515 .unwrap_or_else(|| {
516 self.module
517 .sections
518 .push(RawModuleDefV10Section::Typespace(Typespace::EMPTY.clone()));
519 self.module.sections.len() - 1
520 });
521
522 match &mut self.module.sections[idx] {
523 RawModuleDefV10Section::Typespace(ts) => ts,
524 _ => unreachable!("Just ensured Typespace section exists"),
525 }
526 }
527
528 fn reducers_mut(&mut self) -> &mut Vec<RawReducerDefV10> {
530 let idx = self
531 .module
532 .sections
533 .iter()
534 .position(|s| matches!(s, RawModuleDefV10Section::Reducers(_)))
535 .unwrap_or_else(|| {
536 self.module.sections.push(RawModuleDefV10Section::Reducers(Vec::new()));
537 self.module.sections.len() - 1
538 });
539
540 match &mut self.module.sections[idx] {
541 RawModuleDefV10Section::Reducers(reducers) => reducers,
542 _ => unreachable!("Just ensured Reducers section exists"),
543 }
544 }
545
546 fn procedures_mut(&mut self) -> &mut Vec<RawProcedureDefV10> {
548 let idx = self
549 .module
550 .sections
551 .iter()
552 .position(|s| matches!(s, RawModuleDefV10Section::Procedures(_)))
553 .unwrap_or_else(|| {
554 self.module
555 .sections
556 .push(RawModuleDefV10Section::Procedures(Vec::new()));
557 self.module.sections.len() - 1
558 });
559
560 match &mut self.module.sections[idx] {
561 RawModuleDefV10Section::Procedures(procedures) => procedures,
562 _ => unreachable!("Just ensured Procedures section exists"),
563 }
564 }
565
566 fn views_mut(&mut self) -> &mut Vec<RawViewDefV10> {
568 let idx = self
569 .module
570 .sections
571 .iter()
572 .position(|s| matches!(s, RawModuleDefV10Section::Views(_)))
573 .unwrap_or_else(|| {
574 self.module.sections.push(RawModuleDefV10Section::Views(Vec::new()));
575 self.module.sections.len() - 1
576 });
577
578 match &mut self.module.sections[idx] {
579 RawModuleDefV10Section::Views(views) => views,
580 _ => unreachable!("Just ensured Views section exists"),
581 }
582 }
583
584 fn schedules_mut(&mut self) -> &mut Vec<RawScheduleDefV10> {
586 let idx = self
587 .module
588 .sections
589 .iter()
590 .position(|s| matches!(s, RawModuleDefV10Section::Schedules(_)))
591 .unwrap_or_else(|| {
592 self.module.sections.push(RawModuleDefV10Section::Schedules(Vec::new()));
593 self.module.sections.len() - 1
594 });
595
596 match &mut self.module.sections[idx] {
597 RawModuleDefV10Section::Schedules(schedules) => schedules,
598 _ => unreachable!("Just ensured Schedules section exists"),
599 }
600 }
601
602 fn lifecycle_reducers_mut(&mut self) -> &mut Vec<RawLifeCycleReducerDefV10> {
604 let idx = self
605 .module
606 .sections
607 .iter()
608 .position(|s| matches!(s, RawModuleDefV10Section::LifeCycleReducers(_)))
609 .unwrap_or_else(|| {
610 self.module
611 .sections
612 .push(RawModuleDefV10Section::LifeCycleReducers(Vec::new()));
613 self.module.sections.len() - 1
614 });
615
616 match &mut self.module.sections[idx] {
617 RawModuleDefV10Section::LifeCycleReducers(lcrs) => lcrs,
618 _ => unreachable!("Just ensured LifeCycleReducers section exists"),
619 }
620 }
621
622 fn types_mut(&mut self) -> &mut Vec<RawTypeDefV10> {
624 let idx = self
625 .module
626 .sections
627 .iter()
628 .position(|s| matches!(s, RawModuleDefV10Section::Types(_)))
629 .unwrap_or_else(|| {
630 self.module.sections.push(RawModuleDefV10Section::Types(Vec::new()));
631 self.module.sections.len() - 1
632 });
633
634 match &mut self.module.sections[idx] {
635 RawModuleDefV10Section::Types(types) => types,
636 _ => unreachable!("Just ensured Types section exists"),
637 }
638 }
639
640 pub fn add_type<T: SpacetimeType>(&mut self) -> AlgebraicType {
644 TypespaceBuilder::add_type::<T>(self)
645 }
646
647 fn row_level_security_mut(&mut self) -> &mut Vec<RawRowLevelSecurityDefV10> {
649 let idx = self
650 .module
651 .sections
652 .iter()
653 .position(|s| matches!(s, RawModuleDefV10Section::RowLevelSecurity(_)))
654 .unwrap_or_else(|| {
655 self.module
656 .sections
657 .push(RawModuleDefV10Section::RowLevelSecurity(Vec::new()));
658 self.module.sections.len() - 1
659 });
660
661 match &mut self.module.sections[idx] {
662 RawModuleDefV10Section::RowLevelSecurity(rls) => rls,
663 _ => unreachable!("Just ensured RowLevelSecurity section exists"),
664 }
665 }
666
667 pub fn build_table(
671 &mut self,
672 source_name: impl Into<RawIdentifier>,
673 product_type_ref: AlgebraicTypeRef,
674 ) -> RawTableDefBuilderV10<'_> {
675 let source_name = source_name.into();
676 RawTableDefBuilderV10 {
677 module: &mut self.module,
678 table: RawTableDefV10 {
679 source_name,
680 product_type_ref,
681 indexes: vec![],
682 constraints: vec![],
683 sequences: vec![],
684 primary_key: ColList::empty(),
685 table_type: TableType::User,
686 table_access: TableAccess::Public,
687 default_values: vec![],
688 },
689 }
690 }
691
692 pub fn build_table_with_new_type(
695 &mut self,
696 table_name: impl Into<RawIdentifier>,
697 product_type: impl Into<ProductType>,
698 custom_ordering: bool,
699 ) -> RawTableDefBuilderV10<'_> {
700 let table_name = table_name.into();
701
702 let product_type_ref = self.add_algebraic_type(
703 [],
704 table_name.clone(),
705 AlgebraicType::from(product_type.into()),
706 custom_ordering,
707 );
708
709 self.build_table(table_name, product_type_ref)
710 }
711
712 pub fn build_table_with_new_type_for_tests(
715 &mut self,
716 table_name: impl Into<RawIdentifier>,
717 mut product_type: ProductType,
718 custom_ordering: bool,
719 ) -> RawTableDefBuilderV10<'_> {
720 self.add_expand_product_type_for_tests(&mut 0, &mut product_type);
721 self.build_table_with_new_type(table_name, product_type, custom_ordering)
722 }
723
724 fn add_expand_type_for_tests(&mut self, name_gen: &mut usize, ty: &mut AlgebraicType) {
725 if ty.is_valid_for_client_type_use() {
726 return;
727 }
728
729 match ty {
730 AlgebraicType::Product(prod_ty) => self.add_expand_product_type_for_tests(name_gen, prod_ty),
731 AlgebraicType::Sum(sum_type) => {
732 if let Some(wrapped) = sum_type.as_option_mut() {
733 self.add_expand_type_for_tests(name_gen, wrapped);
734 } else {
735 for elem in sum_type.variants.iter_mut() {
736 self.add_expand_type_for_tests(name_gen, &mut elem.algebraic_type);
737 }
738 }
739 }
740 AlgebraicType::Array(ty) => {
741 self.add_expand_type_for_tests(name_gen, &mut ty.elem_ty);
742 return;
743 }
744 _ => return,
745 }
746
747 let name = *name_gen;
749 let add_ty = core::mem::replace(ty, AlgebraicType::U8);
750 *ty = AlgebraicType::Ref(self.add_algebraic_type([], format!("gen_{name}"), add_ty, true));
751 *name_gen += 1;
752 }
753
754 fn add_expand_product_type_for_tests(&mut self, name_gen: &mut usize, ty: &mut ProductType) {
755 for elem in ty.elements.iter_mut() {
756 self.add_expand_type_for_tests(name_gen, &mut elem.algebraic_type);
757 }
758 }
759
760 pub fn add_algebraic_type(
770 &mut self,
771 scope: impl IntoIterator<Item = RawIdentifier>,
772 source_name: impl Into<RawIdentifier>,
773 ty: AlgebraicType,
774 custom_ordering: bool,
775 ) -> AlgebraicTypeRef {
776 let ty_ref = self.typespace_mut().add(ty);
777 let scope = scope.into_iter().collect();
778 let source_name = source_name.into();
779 self.types_mut().push(RawTypeDefV10 {
780 source_name: RawScopedTypeNameV10 { source_name, scope },
781 ty: ty_ref,
782 custom_ordering,
783 });
784 ty_ref
787 }
788
789 pub fn add_reducer(&mut self, source_name: impl Into<RawIdentifier>, params: ProductType) {
804 self.reducers_mut().push(RawReducerDefV10 {
805 source_name: source_name.into(),
806 params,
807 visibility: FunctionVisibility::ClientCallable,
808 ok_return_type: reducer_default_ok_return_type(),
809 err_return_type: reducer_default_err_return_type(),
810 });
811 }
812
813 pub fn add_procedure(
824 &mut self,
825 source_name: impl Into<RawIdentifier>,
826 params: ProductType,
827 return_type: AlgebraicType,
828 ) {
829 self.procedures_mut().push(RawProcedureDefV10 {
830 source_name: source_name.into(),
831 params,
832 return_type,
833 visibility: FunctionVisibility::ClientCallable,
834 })
835 }
836
837 pub fn add_view(
839 &mut self,
840 source_name: impl Into<RawIdentifier>,
841 index: usize,
842 is_public: bool,
843 is_anonymous: bool,
844 params: ProductType,
845 return_type: AlgebraicType,
846 ) {
847 self.views_mut().push(RawViewDefV10 {
848 source_name: source_name.into(),
849 index: index as u32,
850 is_public,
851 is_anonymous,
852 params,
853 return_type,
854 });
855 }
856
857 pub fn add_lifecycle_reducer(
861 &mut self,
862 lifecycle_spec: Lifecycle,
863 function_name: impl Into<RawIdentifier>,
864 params: ProductType,
865 ) {
866 let function_name = function_name.into();
867 self.lifecycle_reducers_mut().push(RawLifeCycleReducerDefV10 {
868 lifecycle_spec,
869 function_name: function_name.clone(),
870 });
871
872 self.reducers_mut().push(RawReducerDefV10 {
873 source_name: function_name,
874 params,
875 visibility: FunctionVisibility::Internal,
876 ok_return_type: reducer_default_ok_return_type(),
877 err_return_type: reducer_default_err_return_type(),
878 });
879 }
880
881 pub fn add_schedule(
888 &mut self,
889 table: impl Into<RawIdentifier>,
890 column: impl Into<ColId>,
891 function: impl Into<RawIdentifier>,
892 ) {
893 self.schedules_mut().push(RawScheduleDefV10 {
894 source_name: None,
895 table_name: table.into(),
896 schedule_at_col: column.into(),
897 function_name: function.into(),
898 });
899 }
900
901 pub fn add_row_level_security(&mut self, sql: &str) {
907 self.row_level_security_mut()
908 .push(RawRowLevelSecurityDefV10 { sql: sql.into() });
909 }
910
911 pub fn finish(mut self) -> RawModuleDefV10 {
917 let internal_functions = self
918 .module
919 .lifecycle_reducers()
920 .cloned()
921 .into_iter()
922 .flatten()
923 .map(|lcr| lcr.function_name.clone())
924 .chain(
925 self.module
926 .schedules()
927 .cloned()
928 .into_iter()
929 .flatten()
930 .map(|sched| sched.function_name.clone()),
931 );
932
933 for internal_function in internal_functions {
934 if let Some(r) = self
935 .reducers_mut()
936 .iter_mut()
937 .find(|r| r.source_name == internal_function)
938 {
939 r.visibility = FunctionVisibility::Internal;
940 }
941
942 if let Some(p) = self
943 .procedures_mut()
944 .iter_mut()
945 .find(|p| p.source_name == internal_function)
946 {
947 p.visibility = FunctionVisibility::Internal;
948 }
949 }
950 self.module
951 }
952}
953
954impl TypespaceBuilder for RawModuleDefV10Builder {
956 fn add(
957 &mut self,
958 typeid: TypeId,
959 source_name: Option<&'static str>,
960 make_ty: impl FnOnce(&mut Self) -> AlgebraicType,
961 ) -> AlgebraicType {
962 if let btree_map::Entry::Occupied(o) = self.type_map.entry(typeid) {
963 AlgebraicType::Ref(*o.get())
964 } else {
965 let slot_ref = {
966 let ts = self.typespace_mut();
967 let slot_ref = ts.add(AlgebraicType::unit());
969 self.type_map.insert(typeid, slot_ref);
971
972 if let Some(sats_name) = source_name {
974 let source_name = sats_name_to_scoped_name_v10(sats_name);
975
976 self.types_mut().push(RawTypeDefV10 {
977 source_name,
978 ty: slot_ref,
979 custom_ordering: true,
984 });
985 }
986 slot_ref
987 };
988
989 let ty = make_ty(self);
991 self.typespace_mut()[slot_ref] = ty;
992 AlgebraicType::Ref(slot_ref)
993 }
994 }
995}
996
997pub fn reducer_default_ok_return_type() -> AlgebraicType {
998 AlgebraicType::unit()
999}
1000
1001pub fn reducer_default_err_return_type() -> AlgebraicType {
1002 AlgebraicType::String
1003}
1004
1005pub fn sats_name_to_scoped_name_v10(sats_name: &str) -> RawScopedTypeNameV10 {
1009 let mut scope: Vec<RawIdentifier> = sats_name.split("::").flat_map(|s| s.split('.')).map_into().collect();
1011 let source_name = scope.pop().unwrap_or_default();
1013 RawScopedTypeNameV10 {
1014 scope: scope.into(),
1015 source_name,
1016 }
1017}
1018
1019pub struct RawTableDefBuilderV10<'a> {
1021 module: &'a mut RawModuleDefV10,
1022 table: RawTableDefV10,
1023}
1024
1025impl RawTableDefBuilderV10<'_> {
1026 pub fn with_type(mut self, table_type: TableType) -> Self {
1031 self.table.table_type = table_type;
1032 self
1033 }
1034
1035 pub fn with_access(mut self, table_access: TableAccess) -> Self {
1037 self.table.table_access = table_access;
1038 self
1039 }
1040
1041 pub fn with_unique_constraint(mut self, columns: impl Into<ColList>) -> Self {
1043 let columns = columns.into();
1044 self.table.constraints.push(RawConstraintDefV10 {
1045 source_name: None,
1046 data: RawConstraintDataV10::Unique(RawUniqueConstraintDataV10 { columns }),
1047 });
1048
1049 self
1050 }
1051
1052 pub fn with_primary_key(mut self, column: impl Into<ColId>) -> Self {
1055 self.table.primary_key = ColList::new(column.into());
1056 self
1057 }
1058
1059 pub fn with_auto_inc_primary_key(self, column: impl Into<ColId>) -> Self {
1062 let column = column.into();
1063 self.with_primary_key(column)
1064 .with_unique_constraint(column)
1065 .with_column_sequence(column)
1066 }
1067
1068 pub fn with_index(mut self, algorithm: RawIndexAlgorithm, accessor_name: impl Into<RawIdentifier>) -> Self {
1070 let accessor_name = accessor_name.into();
1071
1072 self.table.indexes.push(RawIndexDefV10 {
1073 source_name: None,
1074 accessor_name: Some(accessor_name),
1075 algorithm,
1076 });
1077 self
1078 }
1079
1080 pub fn with_index_no_accessor_name(mut self, algorithm: RawIndexAlgorithm) -> Self {
1082 self.table.indexes.push(RawIndexDefV10 {
1083 source_name: None,
1084 accessor_name: None,
1085 algorithm,
1086 });
1087 self
1088 }
1089
1090 pub fn with_column_sequence(mut self, column: impl Into<ColId>) -> Self {
1092 let column = column.into();
1093 self.table.sequences.push(RawSequenceDefV10 {
1094 source_name: None,
1095 column,
1096 start: None,
1097 min_value: None,
1098 max_value: None,
1099 increment: 1,
1100 });
1101
1102 self
1103 }
1104
1105 pub fn with_default_column_value(mut self, column: impl Into<ColId>, value: AlgebraicValue) -> Self {
1107 let col_id = column.into();
1108 self.table.default_values.push(RawColumnDefaultValueV10 {
1109 col_id,
1110 value: spacetimedb_sats::bsatn::to_vec(&value).unwrap().into(),
1111 });
1112
1113 self
1114 }
1115
1116 pub fn finish(self) -> AlgebraicTypeRef {
1118 let product_type_ref = self.table.product_type_ref;
1119
1120 let tables = match self
1121 .module
1122 .sections
1123 .iter_mut()
1124 .find(|s| matches!(s, RawModuleDefV10Section::Tables(_)))
1125 {
1126 Some(RawModuleDefV10Section::Tables(t)) => t,
1127 _ => {
1128 self.module.sections.push(RawModuleDefV10Section::Tables(Vec::new()));
1129 match self.module.sections.last_mut().expect("Just pushed Tables section") {
1130 RawModuleDefV10Section::Tables(t) => t,
1131 _ => unreachable!(),
1132 }
1133 }
1134 };
1135
1136 tables.push(self.table);
1137 product_type_ref
1138 }
1139
1140 pub fn find_col_pos_by_name(&self, column: impl AsRef<str>) -> Option<ColId> {
1142 let column = column.as_ref();
1143
1144 let typespace = self.module.sections.iter().find_map(|s| {
1145 if let RawModuleDefV10Section::Typespace(ts) = s {
1146 Some(ts)
1147 } else {
1148 None
1149 }
1150 })?;
1151
1152 typespace
1153 .get(self.table.product_type_ref)?
1154 .as_product()?
1155 .elements
1156 .iter()
1157 .position(|e| e.name().is_some_and(|n| n == column))
1158 .map(|i| ColId(i as u16))
1159 }
1160}