1use crate::db::raw_def::v9::{Lifecycle, RawIndexAlgorithm, TableAccess, TableType};
9use core::fmt;
10use spacetimedb_primitives::{ColId, ColList};
11use spacetimedb_sats::raw_identifier::RawIdentifier;
12use spacetimedb_sats::typespace::TypespaceBuilder;
13use spacetimedb_sats::{AlgebraicType, AlgebraicTypeRef, AlgebraicValue, ProductType, SpacetimeType, Typespace};
14use std::any::TypeId;
15use std::collections::{btree_map, BTreeMap};
16
17#[derive(Default, Debug, Clone, SpacetimeType)]
35#[sats(crate = crate)]
36#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
37pub struct RawModuleDefV10 {
38 pub sections: Vec<RawModuleDefV10Section>,
42}
43
44#[derive(Debug, Clone, SpacetimeType)]
48#[sats(crate = crate)]
49#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
50#[non_exhaustive]
51pub enum RawModuleDefV10Section {
52 Typespace(Typespace),
57
58 Types(Vec<RawTypeDefV10>),
60
61 Tables(Vec<RawTableDefV10>),
63
64 Reducers(Vec<RawReducerDefV10>),
66
67 Procedures(Vec<RawProcedureDefV10>),
69
70 Views(Vec<RawViewDefV10>),
72
73 Schedules(Vec<RawScheduleDefV10>),
78
79 LifeCycleReducers(Vec<RawLifeCycleReducerDefV10>),
84
85 RowLevelSecurity(Vec<RawRowLevelSecurityDefV10>), CaseConversionPolicy(CaseConversionPolicy),
89
90 ExplicitNames(ExplicitNames),
92
93 HttpHandlers(Vec<RawHttpHandlerDefV10>),
95
96 HttpRoutes(Vec<RawHttpRouteDefV10>),
98
99 ViewPrimaryKeys(Vec<RawViewPrimaryKeyDefV10>),
101}
102
103#[derive(Debug, Clone, SpacetimeType)]
104#[sats(crate = crate)]
105#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
106pub struct RawHttpHandlerDefV10 {
107 pub source_name: RawIdentifier,
108}
109
110#[derive(Debug, Clone, SpacetimeType)]
111#[sats(crate = crate)]
112#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
113pub struct RawHttpRouteDefV10 {
114 pub handler_function: RawIdentifier,
115 pub method: MethodOrAny,
116 pub path: RawIdentifier,
117}
118
119#[derive(Debug, Clone, SpacetimeType, PartialEq, Eq, PartialOrd, Ord)]
120#[sats(crate = crate)]
121#[non_exhaustive]
122pub enum MethodOrAny {
123 Any,
124 Method(crate::http::Method),
125}
126
127#[derive(Debug, Clone, Copy, Default, SpacetimeType)]
128#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
129#[sats(crate = crate)]
130#[non_exhaustive]
131pub enum CaseConversionPolicy {
132 None,
134 #[default]
136 SnakeCase,
137}
138
139#[derive(Debug, Clone, SpacetimeType)]
140#[sats(crate = crate)]
141#[cfg_attr(feature = "test", derive(PartialEq, Eq, Ord, PartialOrd))]
142#[non_exhaustive]
143pub struct NameMapping {
144 pub source_name: RawIdentifier,
154
155 pub canonical_name: RawIdentifier,
165}
166
167#[derive(Debug, Clone, SpacetimeType)]
168#[sats(crate = crate)]
169#[cfg_attr(feature = "test", derive(PartialEq, Eq, Ord, PartialOrd))]
170#[non_exhaustive]
171pub enum ExplicitNameEntry {
172 Table(NameMapping),
173 Function(NameMapping),
174 Index(NameMapping),
175}
176
177#[derive(Debug, Default, Clone, SpacetimeType)]
178#[sats(crate = crate)]
179#[cfg_attr(feature = "test", derive(PartialEq, Eq, Ord, PartialOrd))]
180#[non_exhaustive]
181pub struct ExplicitNames {
182 entries: Vec<ExplicitNameEntry>,
187}
188
189impl ExplicitNames {
190 fn insert(&mut self, entry: ExplicitNameEntry) {
191 self.entries.push(entry);
192 }
193
194 pub fn insert_table(&mut self, source_name: impl Into<RawIdentifier>, canonical_name: impl Into<RawIdentifier>) {
195 self.insert(ExplicitNameEntry::Table(NameMapping {
196 source_name: source_name.into(),
197 canonical_name: canonical_name.into(),
198 }));
199 }
200
201 pub fn insert_function(&mut self, source_name: impl Into<RawIdentifier>, canonical_name: impl Into<RawIdentifier>) {
202 self.insert(ExplicitNameEntry::Function(NameMapping {
203 source_name: source_name.into(),
204 canonical_name: canonical_name.into(),
205 }));
206 }
207
208 pub fn insert_index(&mut self, source_name: impl Into<RawIdentifier>, canonical_name: impl Into<RawIdentifier>) {
209 self.insert(ExplicitNameEntry::Index(NameMapping {
210 source_name: source_name.into(),
211 canonical_name: canonical_name.into(),
212 }));
213 }
214
215 pub fn merge(&mut self, other: ExplicitNames) {
216 self.entries.extend(other.entries);
217 }
218
219 pub fn into_entries(self) -> Vec<ExplicitNameEntry> {
220 self.entries
221 }
222}
223
224pub type RawRowLevelSecurityDefV10 = crate::db::raw_def::v9::RawRowLevelSecurityDefV9;
225
226#[derive(Debug, Clone, SpacetimeType)]
235#[sats(crate = crate)]
236#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
237pub struct RawTableDefV10 {
238 pub source_name: RawIdentifier,
242
243 pub product_type_ref: AlgebraicTypeRef,
250
251 pub primary_key: ColList,
260
261 pub indexes: Vec<RawIndexDefV10>,
263
264 pub constraints: Vec<RawConstraintDefV10>,
266
267 pub sequences: Vec<RawSequenceDefV10>,
269
270 pub table_type: TableType,
272
273 pub table_access: TableAccess,
275
276 pub default_values: Vec<RawColumnDefaultValueV10>,
278
279 pub is_event: bool,
285}
286
287#[derive(Debug, Clone, SpacetimeType)]
289#[sats(crate = crate)]
290#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
291pub struct RawColumnDefaultValueV10 {
292 pub col_id: ColId,
294
295 pub value: Box<[u8]>,
298}
299
300#[derive(Debug, Clone, SpacetimeType)]
302#[sats(crate = crate)]
303#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
304pub struct RawReducerDefV10 {
305 pub source_name: RawIdentifier,
307
308 pub params: ProductType,
311
312 pub visibility: FunctionVisibility,
314
315 pub ok_return_type: AlgebraicType,
317
318 pub err_return_type: AlgebraicType,
320}
321
322#[derive(Debug, Copy, Clone, SpacetimeType)]
324#[sats(crate = crate)]
325#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
326pub enum FunctionVisibility {
327 Private,
334
335 ClientCallable,
337}
338
339#[derive(Debug, Clone, SpacetimeType)]
341#[sats(crate = crate)]
342#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
343pub struct RawScheduleDefV10 {
344 pub source_name: Option<RawIdentifier>,
348
349 pub table_name: RawIdentifier,
351
352 pub schedule_at_col: ColId,
354
355 pub function_name: RawIdentifier,
357}
358
359#[derive(Debug, Clone, SpacetimeType)]
361#[sats(crate = crate)]
362#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
363pub struct RawLifeCycleReducerDefV10 {
364 pub lifecycle_spec: Lifecycle,
366
367 pub function_name: RawIdentifier,
369}
370
371#[derive(Debug, Clone, SpacetimeType)]
373#[sats(crate = crate)]
374#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
375pub struct RawProcedureDefV10 {
376 pub source_name: RawIdentifier,
378
379 pub params: ProductType,
382
383 pub return_type: AlgebraicType,
388
389 pub visibility: FunctionVisibility,
391}
392
393#[derive(Debug, Clone, SpacetimeType)]
395#[sats(crate = crate)]
396#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
397pub struct RawSequenceDefV10 {
398 pub source_name: Option<RawIdentifier>,
402
403 pub column: ColId,
408
409 pub start: Option<i128>,
413
414 pub min_value: Option<i128>,
417
418 pub max_value: Option<i128>,
421
422 pub increment: i128,
424}
425
426#[derive(Debug, Clone, SpacetimeType)]
428#[sats(crate = crate)]
429#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
430pub struct RawIndexDefV10 {
431 pub source_name: Option<RawIdentifier>,
434
435 pub accessor_name: Option<RawIdentifier>,
438
439 pub algorithm: RawIndexAlgorithm,
441}
442
443#[derive(Debug, Clone, SpacetimeType)]
445#[sats(crate = crate)]
446#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
447pub struct RawConstraintDefV10 {
448 pub source_name: Option<RawIdentifier>,
451
452 pub data: RawConstraintDataV10,
454}
455
456type RawConstraintDataV10 = crate::db::raw_def::v9::RawConstraintDataV9;
457type RawUniqueConstraintDataV10 = crate::db::raw_def::v9::RawUniqueConstraintDataV9;
458
459#[derive(Debug, Clone, SpacetimeType)]
463#[sats(crate = crate)]
464#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
465pub struct RawTypeDefV10 {
466 pub source_name: RawScopedTypeNameV10,
468
469 pub ty: AlgebraicTypeRef,
472
473 pub custom_ordering: bool,
475}
476
477#[derive(Clone, SpacetimeType, PartialEq, Eq, PartialOrd, Ord)]
482#[sats(crate = crate)]
483pub struct RawScopedTypeNameV10 {
484 pub scope: Box<[RawIdentifier]>,
489
490 pub source_name: RawIdentifier,
494}
495
496impl fmt::Debug for RawScopedTypeNameV10 {
497 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
498 for module in self.scope.iter() {
499 fmt::Debug::fmt(module, f)?;
500 f.write_str("::")?;
501 }
502 fmt::Debug::fmt(&self.source_name, f)?;
503 Ok(())
504 }
505}
506
507#[derive(Debug, Clone, SpacetimeType)]
509#[sats(crate = crate)]
510#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
511pub struct RawViewDefV10 {
512 pub source_name: RawIdentifier,
514
515 pub index: u32,
517
518 pub is_public: bool,
522
523 pub is_anonymous: bool,
528
529 pub params: ProductType,
532
533 pub return_type: AlgebraicType,
543}
544
545#[derive(Debug, Clone, SpacetimeType)]
547#[sats(crate = crate)]
548#[cfg_attr(feature = "test", derive(PartialEq, Eq, PartialOrd, Ord))]
549pub struct RawViewPrimaryKeyDefV10 {
550 pub view_source_name: RawIdentifier,
552
553 pub columns: Vec<RawIdentifier>,
558}
559
560impl RawModuleDefV10 {
561 pub fn types(&self) -> Option<&Vec<RawTypeDefV10>> {
563 self.sections.iter().find_map(|s| match s {
564 RawModuleDefV10Section::Types(types) => Some(types),
565 _ => None,
566 })
567 }
568
569 pub fn tables(&self) -> Option<&Vec<RawTableDefV10>> {
571 self.sections.iter().find_map(|s| match s {
572 RawModuleDefV10Section::Tables(tables) => Some(tables),
573 _ => None,
574 })
575 }
576
577 pub fn typespace(&self) -> Option<&Typespace> {
579 self.sections.iter().find_map(|s| match s {
580 RawModuleDefV10Section::Typespace(ts) => Some(ts),
581 _ => None,
582 })
583 }
584
585 pub fn reducers(&self) -> Option<&Vec<RawReducerDefV10>> {
587 self.sections.iter().find_map(|s| match s {
588 RawModuleDefV10Section::Reducers(reducers) => Some(reducers),
589 _ => None,
590 })
591 }
592
593 pub fn procedures(&self) -> Option<&Vec<RawProcedureDefV10>> {
595 self.sections.iter().find_map(|s| match s {
596 RawModuleDefV10Section::Procedures(procedures) => Some(procedures),
597 _ => None,
598 })
599 }
600
601 pub fn views(&self) -> Option<&Vec<RawViewDefV10>> {
603 self.sections.iter().find_map(|s| match s {
604 RawModuleDefV10Section::Views(views) => Some(views),
605 _ => None,
606 })
607 }
608
609 pub fn view_primary_keys(&self) -> Option<&Vec<RawViewPrimaryKeyDefV10>> {
611 self.sections.iter().find_map(|s| match s {
612 RawModuleDefV10Section::ViewPrimaryKeys(primary_keys) => Some(primary_keys),
613 _ => None,
614 })
615 }
616
617 pub fn schedules(&self) -> Option<&Vec<RawScheduleDefV10>> {
619 self.sections.iter().find_map(|s| match s {
620 RawModuleDefV10Section::Schedules(schedules) => Some(schedules),
621 _ => None,
622 })
623 }
624
625 pub fn lifecycle_reducers(&self) -> Option<&Vec<RawLifeCycleReducerDefV10>> {
627 self.sections.iter().find_map(|s| match s {
628 RawModuleDefV10Section::LifeCycleReducers(lcrs) => Some(lcrs),
629 _ => None,
630 })
631 }
632
633 pub fn tables_mut_for_tests(&mut self) -> &mut Vec<RawTableDefV10> {
634 self.sections
635 .iter_mut()
636 .find_map(|s| match s {
637 RawModuleDefV10Section::Tables(tables) => Some(tables),
638 _ => None,
639 })
640 .expect("Tables section must exist for tests")
641 }
642
643 pub fn row_level_security(&self) -> Option<&Vec<RawRowLevelSecurityDefV10>> {
645 self.sections.iter().find_map(|s| match s {
646 RawModuleDefV10Section::RowLevelSecurity(rls) => Some(rls),
647 _ => None,
648 })
649 }
650
651 pub fn case_conversion_policy(&self) -> CaseConversionPolicy {
652 self.sections
653 .iter()
654 .find_map(|s| match s {
655 RawModuleDefV10Section::CaseConversionPolicy(policy) => Some(*policy),
656 _ => None,
657 })
658 .unwrap_or_default()
659 }
660
661 pub fn explicit_names(&self) -> Option<&ExplicitNames> {
662 self.sections.iter().find_map(|s| match s {
663 RawModuleDefV10Section::ExplicitNames(names) => Some(names),
664 _ => None,
665 })
666 }
667
668 pub fn http_handlers(&self) -> Option<&Vec<RawHttpHandlerDefV10>> {
669 self.sections.iter().find_map(|s| match s {
670 RawModuleDefV10Section::HttpHandlers(handlers) => Some(handlers),
671 _ => None,
672 })
673 }
674
675 pub fn http_routes(&self) -> Option<&Vec<RawHttpRouteDefV10>> {
676 self.sections.iter().find_map(|s| match s {
677 RawModuleDefV10Section::HttpRoutes(routes) => Some(routes),
678 _ => None,
679 })
680 }
681}
682
683#[derive(Default)]
685pub struct RawModuleDefV10Builder {
686 module: RawModuleDefV10,
688
689 type_map: BTreeMap<TypeId, AlgebraicTypeRef>,
691}
692
693impl RawModuleDefV10Builder {
694 pub fn new() -> Self {
696 Default::default()
697 }
698
699 fn typespace_mut(&mut self) -> &mut Typespace {
701 let idx = self
702 .module
703 .sections
704 .iter()
705 .position(|s| matches!(s, RawModuleDefV10Section::Typespace(_)))
706 .unwrap_or_else(|| {
707 self.module
708 .sections
709 .push(RawModuleDefV10Section::Typespace(Typespace::EMPTY.clone()));
710 self.module.sections.len() - 1
711 });
712
713 match &mut self.module.sections[idx] {
714 RawModuleDefV10Section::Typespace(ts) => ts,
715 _ => unreachable!("Just ensured Typespace section exists"),
716 }
717 }
718
719 fn reducers_mut(&mut self) -> &mut Vec<RawReducerDefV10> {
721 let idx = self
722 .module
723 .sections
724 .iter()
725 .position(|s| matches!(s, RawModuleDefV10Section::Reducers(_)))
726 .unwrap_or_else(|| {
727 self.module.sections.push(RawModuleDefV10Section::Reducers(Vec::new()));
728 self.module.sections.len() - 1
729 });
730
731 match &mut self.module.sections[idx] {
732 RawModuleDefV10Section::Reducers(reducers) => reducers,
733 _ => unreachable!("Just ensured Reducers section exists"),
734 }
735 }
736
737 fn procedures_mut(&mut self) -> &mut Vec<RawProcedureDefV10> {
739 let idx = self
740 .module
741 .sections
742 .iter()
743 .position(|s| matches!(s, RawModuleDefV10Section::Procedures(_)))
744 .unwrap_or_else(|| {
745 self.module
746 .sections
747 .push(RawModuleDefV10Section::Procedures(Vec::new()));
748 self.module.sections.len() - 1
749 });
750
751 match &mut self.module.sections[idx] {
752 RawModuleDefV10Section::Procedures(procedures) => procedures,
753 _ => unreachable!("Just ensured Procedures section exists"),
754 }
755 }
756
757 fn views_mut(&mut self) -> &mut Vec<RawViewDefV10> {
759 let idx = self
760 .module
761 .sections
762 .iter()
763 .position(|s| matches!(s, RawModuleDefV10Section::Views(_)))
764 .unwrap_or_else(|| {
765 self.module.sections.push(RawModuleDefV10Section::Views(Vec::new()));
766 self.module.sections.len() - 1
767 });
768
769 match &mut self.module.sections[idx] {
770 RawModuleDefV10Section::Views(views) => views,
771 _ => unreachable!("Just ensured Views section exists"),
772 }
773 }
774
775 fn view_primary_keys_mut(&mut self) -> &mut Vec<RawViewPrimaryKeyDefV10> {
777 let idx = self
778 .module
779 .sections
780 .iter()
781 .position(|s| matches!(s, RawModuleDefV10Section::ViewPrimaryKeys(_)))
782 .unwrap_or_else(|| {
783 self.module
784 .sections
785 .push(RawModuleDefV10Section::ViewPrimaryKeys(Vec::new()));
786 self.module.sections.len() - 1
787 });
788
789 match &mut self.module.sections[idx] {
790 RawModuleDefV10Section::ViewPrimaryKeys(primary_keys) => primary_keys,
791 _ => unreachable!("Just ensured ViewPrimaryKeys section exists"),
792 }
793 }
794
795 fn schedules_mut(&mut self) -> &mut Vec<RawScheduleDefV10> {
797 let idx = self
798 .module
799 .sections
800 .iter()
801 .position(|s| matches!(s, RawModuleDefV10Section::Schedules(_)))
802 .unwrap_or_else(|| {
803 self.module.sections.push(RawModuleDefV10Section::Schedules(Vec::new()));
804 self.module.sections.len() - 1
805 });
806
807 match &mut self.module.sections[idx] {
808 RawModuleDefV10Section::Schedules(schedules) => schedules,
809 _ => unreachable!("Just ensured Schedules section exists"),
810 }
811 }
812
813 fn lifecycle_reducers_mut(&mut self) -> &mut Vec<RawLifeCycleReducerDefV10> {
815 let idx = self
816 .module
817 .sections
818 .iter()
819 .position(|s| matches!(s, RawModuleDefV10Section::LifeCycleReducers(_)))
820 .unwrap_or_else(|| {
821 self.module
822 .sections
823 .push(RawModuleDefV10Section::LifeCycleReducers(Vec::new()));
824 self.module.sections.len() - 1
825 });
826
827 match &mut self.module.sections[idx] {
828 RawModuleDefV10Section::LifeCycleReducers(lcrs) => lcrs,
829 _ => unreachable!("Just ensured LifeCycleReducers section exists"),
830 }
831 }
832
833 fn types_mut(&mut self) -> &mut Vec<RawTypeDefV10> {
835 let idx = self
836 .module
837 .sections
838 .iter()
839 .position(|s| matches!(s, RawModuleDefV10Section::Types(_)))
840 .unwrap_or_else(|| {
841 self.module.sections.push(RawModuleDefV10Section::Types(Vec::new()));
842 self.module.sections.len() - 1
843 });
844
845 match &mut self.module.sections[idx] {
846 RawModuleDefV10Section::Types(types) => types,
847 _ => unreachable!("Just ensured Types section exists"),
848 }
849 }
850
851 pub fn add_type<T: SpacetimeType>(&mut self) -> AlgebraicType {
855 TypespaceBuilder::add_type::<T>(self)
856 }
857
858 fn row_level_security_mut(&mut self) -> &mut Vec<RawRowLevelSecurityDefV10> {
860 let idx = self
861 .module
862 .sections
863 .iter()
864 .position(|s| matches!(s, RawModuleDefV10Section::RowLevelSecurity(_)))
865 .unwrap_or_else(|| {
866 self.module
867 .sections
868 .push(RawModuleDefV10Section::RowLevelSecurity(Vec::new()));
869 self.module.sections.len() - 1
870 });
871
872 match &mut self.module.sections[idx] {
873 RawModuleDefV10Section::RowLevelSecurity(rls) => rls,
874 _ => unreachable!("Just ensured RowLevelSecurity section exists"),
875 }
876 }
877
878 fn explicit_names_mut(&mut self) -> &mut ExplicitNames {
880 let idx = self
881 .module
882 .sections
883 .iter()
884 .position(|s| matches!(s, RawModuleDefV10Section::ExplicitNames(_)))
885 .unwrap_or_else(|| {
886 self.module
887 .sections
888 .push(RawModuleDefV10Section::ExplicitNames(ExplicitNames::default()));
889 self.module.sections.len() - 1
890 });
891
892 match &mut self.module.sections[idx] {
893 RawModuleDefV10Section::ExplicitNames(names) => names,
894 _ => unreachable!("Just ensured ExplicitNames section exists"),
895 }
896 }
897
898 fn http_handlers_mut(&mut self) -> &mut Vec<RawHttpHandlerDefV10> {
900 let idx = self
901 .module
902 .sections
903 .iter()
904 .position(|s| matches!(s, RawModuleDefV10Section::HttpHandlers(_)))
905 .unwrap_or_else(|| {
906 self.module
907 .sections
908 .push(RawModuleDefV10Section::HttpHandlers(Vec::new()));
909 self.module.sections.len() - 1
910 });
911
912 match &mut self.module.sections[idx] {
913 RawModuleDefV10Section::HttpHandlers(handlers) => handlers,
914 _ => unreachable!("Just ensured HttpHandlers section exists"),
915 }
916 }
917
918 fn http_routes_mut(&mut self) -> &mut Vec<RawHttpRouteDefV10> {
920 let idx = self
921 .module
922 .sections
923 .iter()
924 .position(|s| matches!(s, RawModuleDefV10Section::HttpRoutes(_)))
925 .unwrap_or_else(|| {
926 self.module
927 .sections
928 .push(RawModuleDefV10Section::HttpRoutes(Vec::new()));
929 self.module.sections.len() - 1
930 });
931
932 match &mut self.module.sections[idx] {
933 RawModuleDefV10Section::HttpRoutes(routes) => routes,
934 _ => unreachable!("Just ensured HttpRoutes section exists"),
935 }
936 }
937
938 pub fn build_table(
942 &mut self,
943 source_name: impl Into<RawIdentifier>,
944 product_type_ref: AlgebraicTypeRef,
945 ) -> RawTableDefBuilderV10<'_> {
946 let source_name = source_name.into();
947 RawTableDefBuilderV10 {
948 module: &mut self.module,
949 table: RawTableDefV10 {
950 source_name,
951 product_type_ref,
952 indexes: vec![],
953 constraints: vec![],
954 sequences: vec![],
955 primary_key: ColList::empty(),
956 table_type: TableType::User,
957 table_access: TableAccess::Public,
958 default_values: vec![],
959 is_event: false,
960 },
961 }
962 }
963
964 pub fn build_table_with_new_type(
967 &mut self,
968 table_name: impl Into<RawIdentifier>,
969 product_type: impl Into<ProductType>,
970 custom_ordering: bool,
971 ) -> RawTableDefBuilderV10<'_> {
972 let table_name = table_name.into();
973
974 let product_type_ref = self.add_algebraic_type(
975 [],
976 table_name.clone(),
977 AlgebraicType::from(product_type.into()),
978 custom_ordering,
979 );
980
981 self.build_table(table_name, product_type_ref)
982 }
983
984 pub fn build_table_with_new_type_for_tests(
987 &mut self,
988 table_name: impl Into<RawIdentifier>,
989 mut product_type: ProductType,
990 custom_ordering: bool,
991 ) -> RawTableDefBuilderV10<'_> {
992 self.add_expand_product_type_for_tests(&mut 0, &mut product_type);
993 self.build_table_with_new_type(table_name, product_type, custom_ordering)
994 }
995
996 fn add_expand_type_for_tests(&mut self, name_gen: &mut usize, ty: &mut AlgebraicType) {
997 if ty.is_valid_for_client_type_use() {
998 return;
999 }
1000
1001 match ty {
1002 AlgebraicType::Product(prod_ty) => self.add_expand_product_type_for_tests(name_gen, prod_ty),
1003 AlgebraicType::Sum(sum_type) => {
1004 if let Some(wrapped) = sum_type.as_option_mut() {
1005 self.add_expand_type_for_tests(name_gen, wrapped);
1006 } else {
1007 for elem in sum_type.variants.iter_mut() {
1008 self.add_expand_type_for_tests(name_gen, &mut elem.algebraic_type);
1009 }
1010 }
1011 }
1012 AlgebraicType::Array(ty) => {
1013 self.add_expand_type_for_tests(name_gen, &mut ty.elem_ty);
1014 return;
1015 }
1016 _ => return,
1017 }
1018
1019 let name = *name_gen;
1021 let add_ty = core::mem::replace(ty, AlgebraicType::U8);
1022 *ty = AlgebraicType::Ref(self.add_algebraic_type([], RawIdentifier::new(format!("gen_{name}")), add_ty, true));
1023 *name_gen += 1;
1024 }
1025
1026 fn add_expand_product_type_for_tests(&mut self, name_gen: &mut usize, ty: &mut ProductType) {
1027 for elem in ty.elements.iter_mut() {
1028 self.add_expand_type_for_tests(name_gen, &mut elem.algebraic_type);
1029 }
1030 }
1031
1032 pub fn add_algebraic_type(
1042 &mut self,
1043 scope: impl IntoIterator<Item = RawIdentifier>,
1044 source_name: impl Into<RawIdentifier>,
1045 ty: AlgebraicType,
1046 custom_ordering: bool,
1047 ) -> AlgebraicTypeRef {
1048 let ty_ref = self.typespace_mut().add(ty);
1049 let scope = scope.into_iter().collect();
1050 let source_name = source_name.into();
1051 self.types_mut().push(RawTypeDefV10 {
1052 source_name: RawScopedTypeNameV10 { source_name, scope },
1053 ty: ty_ref,
1054 custom_ordering,
1055 });
1056 ty_ref
1059 }
1060
1061 pub fn add_reducer(&mut self, source_name: impl Into<RawIdentifier>, params: ProductType) {
1076 self.reducers_mut().push(RawReducerDefV10 {
1077 source_name: source_name.into(),
1078 params,
1079 visibility: FunctionVisibility::ClientCallable,
1080 ok_return_type: reducer_default_ok_return_type(),
1081 err_return_type: reducer_default_err_return_type(),
1082 });
1083 }
1084
1085 pub fn add_procedure(
1096 &mut self,
1097 source_name: impl Into<RawIdentifier>,
1098 params: ProductType,
1099 return_type: AlgebraicType,
1100 ) {
1101 self.procedures_mut().push(RawProcedureDefV10 {
1102 source_name: source_name.into(),
1103 params,
1104 return_type,
1105 visibility: FunctionVisibility::ClientCallable,
1106 })
1107 }
1108
1109 pub fn add_view(
1111 &mut self,
1112 source_name: impl Into<RawIdentifier>,
1113 index: usize,
1114 is_public: bool,
1115 is_anonymous: bool,
1116 params: ProductType,
1117 return_type: AlgebraicType,
1118 ) {
1119 self.views_mut().push(RawViewDefV10 {
1120 source_name: source_name.into(),
1121 index: index as u32,
1122 is_public,
1123 is_anonymous,
1124 params,
1125 return_type,
1126 });
1127 }
1128
1129 pub fn add_view_primary_key<C, I>(&mut self, view_source_name: impl Into<RawIdentifier>, columns: I)
1131 where
1132 C: Into<RawIdentifier>,
1133 I: IntoIterator<Item = C>,
1134 {
1135 self.view_primary_keys_mut().push(RawViewPrimaryKeyDefV10 {
1136 view_source_name: view_source_name.into(),
1137 columns: columns.into_iter().map(Into::into).collect(),
1138 });
1139 }
1140
1141 pub fn add_lifecycle_reducer(
1145 &mut self,
1146 lifecycle_spec: Lifecycle,
1147 function_name: impl Into<RawIdentifier>,
1148 params: ProductType,
1149 ) {
1150 let function_name = function_name.into();
1151 self.lifecycle_reducers_mut().push(RawLifeCycleReducerDefV10 {
1152 lifecycle_spec,
1153 function_name: function_name.clone(),
1154 });
1155
1156 self.reducers_mut().push(RawReducerDefV10 {
1157 source_name: function_name,
1158 params,
1159 visibility: FunctionVisibility::Private,
1160 ok_return_type: reducer_default_ok_return_type(),
1161 err_return_type: reducer_default_err_return_type(),
1162 });
1163 }
1164
1165 pub fn add_schedule(
1172 &mut self,
1173 table: impl Into<RawIdentifier>,
1174 column: impl Into<ColId>,
1175 function: impl Into<RawIdentifier>,
1176 ) {
1177 self.schedules_mut().push(RawScheduleDefV10 {
1178 source_name: None,
1179 table_name: table.into(),
1180 schedule_at_col: column.into(),
1181 function_name: function.into(),
1182 });
1183 }
1184
1185 pub fn add_row_level_security(&mut self, sql: &str) {
1191 self.row_level_security_mut()
1192 .push(RawRowLevelSecurityDefV10 { sql: sql.into() });
1193 }
1194
1195 pub fn add_http_handler(&mut self, source_name: impl Into<RawIdentifier>) {
1197 self.http_handlers_mut().push(RawHttpHandlerDefV10 {
1198 source_name: source_name.into(),
1199 });
1200 }
1201
1202 pub fn add_http_route(
1204 &mut self,
1205 handler_function: impl Into<RawIdentifier>,
1206 method: MethodOrAny,
1207 path: impl Into<RawIdentifier>,
1208 ) {
1209 self.http_routes_mut().push(RawHttpRouteDefV10 {
1210 handler_function: handler_function.into(),
1211 method,
1212 path: path.into(),
1213 });
1214 }
1215
1216 pub fn add_explicit_names(&mut self, names: ExplicitNames) {
1217 self.explicit_names_mut().merge(names);
1218 }
1219
1220 pub fn set_case_conversion_policy(&mut self, policy: CaseConversionPolicy) {
1227 self.module
1229 .sections
1230 .retain(|s| !matches!(s, RawModuleDefV10Section::CaseConversionPolicy(_)));
1231 self.module
1232 .sections
1233 .push(RawModuleDefV10Section::CaseConversionPolicy(policy));
1234 }
1235
1236 pub fn finish(self) -> RawModuleDefV10 {
1239 self.module
1240 }
1241}
1242
1243impl TypespaceBuilder for RawModuleDefV10Builder {
1245 fn add(
1246 &mut self,
1247 typeid: TypeId,
1248 source_name: Option<&'static str>,
1249 make_ty: impl FnOnce(&mut Self) -> AlgebraicType,
1250 ) -> AlgebraicType {
1251 if let btree_map::Entry::Occupied(o) = self.type_map.entry(typeid) {
1252 AlgebraicType::Ref(*o.get())
1253 } else {
1254 let slot_ref = {
1255 let ts = self.typespace_mut();
1256 let slot_ref = ts.add(AlgebraicType::unit());
1258 self.type_map.insert(typeid, slot_ref);
1260
1261 if let Some(sats_name) = source_name {
1263 let source_name = sats_name_to_scoped_name_v10(sats_name);
1264
1265 self.types_mut().push(RawTypeDefV10 {
1266 source_name,
1267 ty: slot_ref,
1268 custom_ordering: true,
1273 });
1274 }
1275 slot_ref
1276 };
1277
1278 let ty = make_ty(self);
1280 self.typespace_mut()[slot_ref] = ty;
1281 AlgebraicType::Ref(slot_ref)
1282 }
1283 }
1284}
1285
1286pub fn reducer_default_ok_return_type() -> AlgebraicType {
1287 AlgebraicType::unit()
1288}
1289
1290pub fn reducer_default_err_return_type() -> AlgebraicType {
1291 AlgebraicType::String
1292}
1293
1294pub fn sats_name_to_scoped_name_v10(sats_name: &str) -> RawScopedTypeNameV10 {
1298 let mut scope: Vec<RawIdentifier> = sats_name
1300 .split("::")
1301 .flat_map(|s| s.split('.'))
1302 .map(RawIdentifier::new)
1303 .collect();
1304 let source_name = scope.pop().unwrap_or_default();
1306 RawScopedTypeNameV10 {
1307 scope: scope.into(),
1308 source_name,
1309 }
1310}
1311
1312pub struct RawTableDefBuilderV10<'a> {
1314 module: &'a mut RawModuleDefV10,
1315 table: RawTableDefV10,
1316}
1317
1318impl RawTableDefBuilderV10<'_> {
1319 pub fn with_type(mut self, table_type: TableType) -> Self {
1324 self.table.table_type = table_type;
1325 self
1326 }
1327
1328 pub fn with_access(mut self, table_access: TableAccess) -> Self {
1330 self.table.table_access = table_access;
1331 self
1332 }
1333
1334 pub fn with_event(mut self, is_event: bool) -> Self {
1336 self.table.is_event = is_event;
1337 self
1338 }
1339
1340 pub fn with_unique_constraint(mut self, columns: impl Into<ColList>) -> Self {
1342 let columns = columns.into();
1343 self.table.constraints.push(RawConstraintDefV10 {
1344 source_name: None,
1345 data: RawConstraintDataV10::Unique(RawUniqueConstraintDataV10 { columns }),
1346 });
1347
1348 self
1349 }
1350
1351 pub fn with_primary_key(mut self, column: impl Into<ColId>) -> Self {
1354 self.table.primary_key = ColList::new(column.into());
1355 self
1356 }
1357
1358 pub fn with_auto_inc_primary_key(self, column: impl Into<ColId>) -> Self {
1361 let column = column.into();
1362 self.with_primary_key(column)
1363 .with_unique_constraint(column)
1364 .with_column_sequence(column)
1365 }
1366
1367 pub fn with_index(
1369 mut self,
1370 algorithm: RawIndexAlgorithm,
1371 source_name: impl Into<RawIdentifier>,
1372 accessor_name: impl Into<RawIdentifier>,
1373 ) -> Self {
1374 self.table.indexes.push(RawIndexDefV10 {
1375 source_name: Some(source_name.into()),
1376 accessor_name: Some(accessor_name.into()),
1377 algorithm,
1378 });
1379 self
1380 }
1381
1382 pub fn with_index_no_accessor_name(
1384 mut self,
1385 algorithm: RawIndexAlgorithm,
1386 source_name: impl Into<RawIdentifier>,
1387 ) -> Self {
1388 self.table.indexes.push(RawIndexDefV10 {
1389 source_name: Some(source_name.into()),
1390 accessor_name: None,
1391 algorithm,
1392 });
1393 self
1394 }
1395
1396 pub fn with_column_sequence(mut self, column: impl Into<ColId>) -> Self {
1398 let column = column.into();
1399 self.table.sequences.push(RawSequenceDefV10 {
1400 source_name: None,
1401 column,
1402 start: None,
1403 min_value: None,
1404 max_value: None,
1405 increment: 1,
1406 });
1407
1408 self
1409 }
1410
1411 pub fn with_default_column_value(mut self, column: impl Into<ColId>, value: AlgebraicValue) -> Self {
1413 let col_id = column.into();
1414 self.table.default_values.push(RawColumnDefaultValueV10 {
1415 col_id,
1416 value: spacetimedb_sats::bsatn::to_vec(&value).unwrap().into(),
1417 });
1418
1419 self
1420 }
1421
1422 pub fn finish(self) -> AlgebraicTypeRef {
1424 let product_type_ref = self.table.product_type_ref;
1425
1426 let tables = match self
1427 .module
1428 .sections
1429 .iter_mut()
1430 .find(|s| matches!(s, RawModuleDefV10Section::Tables(_)))
1431 {
1432 Some(RawModuleDefV10Section::Tables(t)) => t,
1433 _ => {
1434 self.module.sections.push(RawModuleDefV10Section::Tables(Vec::new()));
1435 match self.module.sections.last_mut().expect("Just pushed Tables section") {
1436 RawModuleDefV10Section::Tables(t) => t,
1437 _ => unreachable!(),
1438 }
1439 }
1440 };
1441
1442 tables.push(self.table);
1443 product_type_ref
1444 }
1445
1446 pub fn find_col_pos_by_name(&self, column: impl AsRef<str>) -> Option<ColId> {
1448 let column = column.as_ref();
1449
1450 let typespace = self.module.sections.iter().find_map(|s| {
1451 if let RawModuleDefV10Section::Typespace(ts) = s {
1452 Some(ts)
1453 } else {
1454 None
1455 }
1456 })?;
1457
1458 typespace
1459 .get(self.table.product_type_ref)?
1460 .as_product()?
1461 .elements
1462 .iter()
1463 .position(|x| x.has_name(column.as_ref()))
1464 .map(|i| ColId(i as u16))
1465 }
1466}