1mod projected_field;
2pub use projected_field::ProjectedField;
3
4use crate::{
5 Schema,
6 schema::{
7 app::{Field, Model, ModelId, ModelRoot},
8 db::{self, Column, Table, TableId},
9 },
10 stmt::{
11 Delete, Expr, ExprArg, ExprFunc, ExprReference, ExprSet, Insert, InsertTarget, Query,
12 Returning, Select, Source, SourceTable, Statement, TableDerived, TableFactor, TableRef,
13 Type, TypeUnion, Update, UpdateTarget,
14 },
15};
16
17#[derive(Debug)]
34pub struct ExprContext<'a, T = Schema> {
35 schema: &'a T,
36 parent: Option<&'a ExprContext<'a, T>>,
37 target: ExprTarget<'a>,
38}
39
40#[derive(Debug)]
52pub enum ResolvedRef<'a> {
53 Column(&'a Column),
62
63 Field(&'a Field),
73
74 Model(&'a ModelRoot),
76
77 Cte {
87 nesting: usize,
89 index: usize,
91 },
92
93 Derived(DerivedRef<'a>),
99}
100
101#[derive(Debug)]
103pub struct DerivedRef<'a> {
104 pub nesting: usize,
106
107 pub index: usize,
109
110 pub derived: &'a TableDerived,
112}
113
114impl DerivedRef<'_> {
115 pub fn is_column_always_null(&self) -> bool {
121 let ExprSet::Values(values) = &self.derived.subquery.body else {
122 return false;
123 };
124
125 if values.is_empty() {
126 return false;
127 }
128
129 values.rows.iter().all(|row| self.row_column_is_null(row))
130 }
131
132 fn row_column_is_null(&self, row: &Expr) -> bool {
133 match row {
134 Expr::Value(super::Value::Record(record)) => {
135 self.index < record.len() && record[self.index].is_null()
136 }
137 Expr::Record(record) => {
138 self.index < record.len()
139 && matches!(&record.fields[self.index], Expr::Value(super::Value::Null))
140 }
141 Expr::Value(super::Value::Null) => true,
142 _ => false,
143 }
144 }
145}
146
147#[derive(Debug, Clone, Copy)]
152pub enum ExprTarget<'a> {
153 Free,
155
156 Model(&'a ModelRoot),
158
159 Table(&'a Table),
163
164 Source(&'a SourceTable),
166}
167
168pub trait Resolve {
174 fn table_for_model(&self, model: &ModelRoot) -> Option<&Table> {
176 let _ = model;
177 None
178 }
179
180 fn model(&self, id: ModelId) -> Option<&Model> {
186 let _ = id;
187 None
188 }
189
190 fn table(&self, id: TableId) -> Option<&Table> {
196 let _ = id;
197 None
198 }
199}
200
201pub trait IntoExprTarget<'a, T = Schema> {
204 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a>;
206}
207
208#[derive(Debug)]
209struct ArgTyStack<'a> {
210 tys: &'a [Type],
211 parent: Option<&'a ArgTyStack<'a>>,
212}
213
214impl<'a, T> ExprContext<'a, T> {
215 pub fn schema(&self) -> &'a T {
217 self.schema
218 }
219
220 pub fn target(&self) -> ExprTarget<'a> {
222 self.target
223 }
224
225 pub fn target_at(&self, nesting: usize) -> &ExprTarget<'a> {
227 &self.context_at(nesting).target
228 }
229
230 fn context_at(&self, nesting: usize) -> &Self {
231 let mut curr = self;
232
233 for _ in 0..nesting {
235 let Some(parent) = curr.parent else {
236 todo!("bug: invalid nesting level");
237 };
238
239 curr = parent;
240 }
241
242 curr
243 }
244}
245
246impl<'a> ExprContext<'a, ()> {
247 pub fn new_free() -> ExprContext<'a, ()> {
249 ExprContext {
250 schema: &(),
251 parent: None,
252 target: ExprTarget::Free,
253 }
254 }
255}
256
257impl<'a, T: Resolve> ExprContext<'a, T> {
258 pub fn new(schema: &'a T) -> ExprContext<'a, T> {
260 ExprContext::new_with_target(schema, ExprTarget::Free)
261 }
262
263 pub fn new_with_target(
265 schema: &'a T,
266 target: impl IntoExprTarget<'a, T>,
267 ) -> ExprContext<'a, T> {
268 let target = target.into_expr_target(schema);
269 ExprContext {
270 schema,
271 parent: None,
272 target,
273 }
274 }
275
276 pub fn scope<'child>(
279 &'child self,
280 target: impl IntoExprTarget<'child, T>,
281 ) -> ExprContext<'child, T> {
283 let target = target.into_expr_target(self.schema);
284 ExprContext {
285 schema: self.schema,
286 parent: Some(self),
287 target,
288 }
289 }
290
291 pub fn resolve_expr_reference(&self, expr_reference: &ExprReference) -> ResolvedRef<'a> {
307 let nesting = match expr_reference {
308 ExprReference::Column(expr_column) => expr_column.nesting,
309 ExprReference::Field { nesting, .. } => *nesting,
310 ExprReference::Model { nesting } => *nesting,
311 };
312
313 let target = self.target_at(nesting);
314
315 match target {
316 ExprTarget::Free => todo!("cannot resolve column in free context"),
317 ExprTarget::Model(model) => match expr_reference {
318 ExprReference::Model { .. } => ResolvedRef::Model(model),
319 ExprReference::Field { index, .. } => ResolvedRef::Field(&model.fields[*index]),
320 ExprReference::Column(expr_column) => {
321 assert_eq!(expr_column.table, 0, "TODO: is this true?");
322
323 let Some(table) = self.schema.table_for_model(model) else {
324 panic!(
325 "Failed to find database table for model '{:?}' - model may not be mapped to a table",
326 model.name
327 )
328 };
329 ResolvedRef::Column(&table.columns[expr_column.column])
330 }
331 },
332 ExprTarget::Table(table) => match expr_reference {
333 ExprReference::Model { .. } => {
334 panic!("Cannot resolve ExprReference::Model in Table target context")
335 }
336 ExprReference::Field { .. } => panic!(
337 "Cannot resolve ExprReference::Field in Table target context - use ExprReference::Column instead"
338 ),
339 ExprReference::Column(expr_column) => {
340 ResolvedRef::Column(&table.columns[expr_column.column])
341 }
342 },
343 ExprTarget::Source(source_table) => {
344 match expr_reference {
345 ExprReference::Column(expr_column) => {
346 let table_ref = &source_table.tables[expr_column.table];
348 match table_ref {
349 TableRef::Table(table_id) => {
350 let Some(table) = self.schema.table(*table_id) else {
351 panic!(
352 "Failed to resolve table with ID {:?} - table not found in schema.",
353 table_id,
354 );
355 };
356 ResolvedRef::Column(&table.columns[expr_column.column])
357 }
358 TableRef::Derived(derived) => ResolvedRef::Derived(DerivedRef {
359 nesting: expr_column.nesting,
360 index: expr_column.column,
361 derived,
362 }),
363 TableRef::Cte {
364 nesting: cte_nesting,
365 index,
366 } => {
367 ResolvedRef::Cte {
369 nesting: expr_column.nesting + cte_nesting,
370 index: *index,
371 }
372 }
373 TableRef::Arg(_) => todo!(),
374 }
375 }
376 ExprReference::Model { .. } => {
377 panic!("Cannot resolve ExprReference::Model in Source::Table context")
378 }
379 ExprReference::Field { .. } => panic!(
380 "Cannot resolve ExprReference::Field in Source::Table context - use ExprReference::Column instead"
381 ),
382 }
383 }
384 }
385 }
386
387 pub fn infer_stmt_ty(&self, stmt: &Statement, args: &[Type]) -> Type {
389 let cx = self.scope(stmt);
390
391 match stmt {
392 Statement::Delete(stmt) => stmt
393 .returning
394 .as_ref()
395 .map(|returning| cx.infer_returning_ty(returning, args, false))
396 .unwrap_or(Type::Unit),
397 Statement::Insert(stmt) => stmt
398 .returning
399 .as_ref()
400 .map(|returning| cx.infer_returning_ty(returning, args, stmt.source.single))
401 .unwrap_or(Type::Unit),
402 Statement::Query(stmt) => match &stmt.body {
403 ExprSet::Select(body) => cx.infer_returning_ty(&body.returning, args, stmt.single),
404 ExprSet::SetOp(_body) => todo!(),
405 ExprSet::Update(_body) => todo!(),
406 ExprSet::Delete(body) => body
407 .returning
408 .as_ref()
409 .map(|returning| cx.infer_returning_ty(returning, args, stmt.single))
410 .unwrap_or(Type::Unit),
411 ExprSet::Values(_body) => todo!(),
412 ExprSet::Insert(body) => body
413 .returning
414 .as_ref()
415 .map(|returning| cx.infer_returning_ty(returning, args, stmt.single))
416 .unwrap_or(Type::Unit),
417 },
418 Statement::Update(stmt) => stmt
419 .returning
420 .as_ref()
421 .map(|returning| cx.infer_returning_ty(returning, args, false))
422 .unwrap_or(Type::Unit),
423 }
424 }
425
426 fn infer_returning_ty(&self, returning: &Returning, args: &[Type], single: bool) -> Type {
427 let arg_ty_stack = ArgTyStack::new(args);
428 self.infer_returning_ty2(returning, &arg_ty_stack, single)
429 }
430
431 fn infer_returning_ty2(
432 &self,
433 returning: &Returning,
434 args: &ArgTyStack<'_>,
435 single: bool,
436 ) -> Type {
437 match returning {
438 Returning::Model { .. } => {
439 let ty = Type::Model(
440 self.target
441 .model_id()
442 .expect("returning `Model` when not in model context"),
443 );
444
445 if single { ty } else { Type::list(ty) }
446 }
447 Returning::Changed => todo!(),
448 Returning::Project(expr) => {
449 let ty = self.infer_expr_ty2(args, expr, false);
450
451 if single { ty } else { Type::list(ty) }
452 }
453 Returning::Expr(expr) => self.infer_expr_ty2(args, expr, true),
454 }
455 }
456
457 pub fn infer_expr_ty(&self, expr: &Expr, args: &[Type]) -> Type {
459 let arg_ty_stack = ArgTyStack::new(args);
460 self.infer_expr_ty2(&arg_ty_stack, expr, false)
461 }
462
463 fn infer_expr_ty2(&self, args: &ArgTyStack<'_>, expr: &Expr, returning_expr: bool) -> Type {
464 match expr {
465 Expr::Arg(e) => args.resolve_arg_ty(e).clone(),
466 Expr::And(_) => Type::Bool,
467 Expr::Any(_) | Expr::AnyOp(_) | Expr::AllOp(_) | Expr::InList(_) => Type::Bool,
468 Expr::BinaryOp(_) => Type::Bool,
469 Expr::Cast(e) => e.ty.clone(),
470 Expr::Reference(expr_ref) => {
471 assert!(
472 !returning_expr,
473 "should have been handled in Expr::Project. Invalid expr?"
474 );
475 self.infer_expr_reference_ty2(expr_ref, args)
476 }
477 Expr::IsNull(_) => Type::Bool,
478 Expr::IsVariant(_) => Type::Bool,
479 Expr::Variant(e) => {
480 let base = self.infer_expr_ty2(args, &e.base, returning_expr);
483 let Type::Model(id) = base else {
484 todo!("variant selection on non-enum type {base:#?}")
485 };
486 assert_eq!(id, e.variant.model, "variant selection on the wrong enum");
487 let Some(Model::EmbeddedEnum(embedded)) = self.schema.model(id) else {
488 todo!("variant selection on non-enum model {id:?}")
489 };
490 Type::Record(
491 embedded
492 .variant_fields(e.variant.index)
493 .iter()
494 .map(|field| field.expr_ty().clone())
495 .collect(),
496 )
497 }
498 Expr::List(e) => {
499 debug_assert!(!e.items.is_empty());
500 Type::list(self.infer_expr_ty2(args, &e.items[0], returning_expr))
501 }
502 Expr::Map(e) => {
503 let base = self.infer_expr_ty2(args, &e.base, returning_expr);
505
506 let Type::List(item) = base else {
508 todo!("error handling; base={base:#?}")
509 };
510
511 let scope_tys = &[*item];
512
513 let args = args.scope(scope_tys);
515
516 let ty = self.infer_expr_ty2(&args, &e.map, returning_expr);
518
519 Type::list(ty)
521 }
522 Expr::Not(_) => Type::Bool,
523 Expr::Or(_) => Type::Bool,
524 Expr::Project(e) => {
525 if returning_expr {
526 match &*e.base {
527 Expr::Arg(expr_arg) => {
528 assert!(e.projection.as_slice().len() == 1);
533 return args.resolve_arg_ty(expr_arg).clone();
534 }
535 Expr::Reference(expr_reference) => {
536 assert!(e.projection.as_slice().len() == 1);
541 return self.infer_expr_reference_ty2(expr_reference, args);
542 }
543 _ => {}
544 }
545 }
546
547 let mut base = self.infer_expr_ty2(args, &e.base, returning_expr);
548
549 for step in e.projection.iter() {
550 base = match base {
551 Type::Record(mut fields) => {
552 std::mem::replace(&mut fields[*step], Type::Null)
553 }
554 Type::Model(id) => match self.schema.model(id) {
561 Some(Model::Root(model)) => model.fields[*step].expr_ty().clone(),
562 Some(Model::EmbeddedStruct(embedded)) => {
563 embedded.fields[*step].expr_ty().clone()
564 }
565 _ => todo!("project into non-embedded model {id:?}"),
566 },
567 Type::List(items) => *items,
568 expr => todo!(
569 "returning_expr={returning_expr:#?}; expr={expr:#?}; project={e:#?}"
570 ),
571 }
572 }
573
574 base
575 }
576 Expr::Record(e) => Type::Record(
577 e.fields
578 .iter()
579 .map(|field| self.infer_expr_ty2(args, field, returning_expr))
580 .collect(),
581 ),
582 Expr::Value(value) | Expr::Static(value) => value.infer_ty(),
583 Expr::Let(expr_let) => {
584 let scope_tys: Vec<_> = expr_let
585 .bindings
586 .iter()
587 .map(|b| self.infer_expr_ty2(args, b, returning_expr))
588 .collect();
589 let args = args.scope(&scope_tys);
590 self.infer_expr_ty2(&args, &expr_let.body, returning_expr)
591 }
592 Expr::Match(expr_match) => {
593 let mut union = TypeUnion::new();
598 for arm in &expr_match.arms {
599 let ty = self.infer_expr_ty2(args, &arm.expr, returning_expr);
600 union.insert(ty);
601 }
602 let else_ty = self.infer_expr_ty2(args, &expr_match.else_expr, returning_expr);
603 union.insert(else_ty);
604 union.simplify()
605 }
606 Expr::Error(_) => Type::Unknown,
610 Expr::Exists(_) => Type::Bool,
611 Expr::Func(ExprFunc::Count(_)) => Type::U64,
612 Expr::Func(ExprFunc::LastInsertId(_)) => Type::I64,
613 Expr::Func(ExprFunc::JsonExtract(func)) => func.ty.clone(),
614 Expr::Incoming(incoming) => match incoming {
615 super::ExprIncoming::Model(model) => Type::Model(*model),
616 super::ExprIncoming::Table(table) => {
617 let table = self.schema.table(*table).unwrap_or_else(|| {
618 panic!("incoming table {table:?} is not present in the schema")
619 });
620 Type::Record(
621 table
622 .columns
623 .iter()
624 .map(|column| column.ty.clone())
625 .collect(),
626 )
627 }
628 },
629 _ => todo!("{expr:#?}"),
630 }
631 }
632
633 pub fn infer_expr_reference_ty(&self, expr_reference: &ExprReference) -> Type {
638 self.infer_expr_reference_ty2(expr_reference, &ArgTyStack::new(&[]))
639 }
640
641 fn infer_expr_reference_ty2(
642 &self,
643 expr_reference: &ExprReference,
644 args: &ArgTyStack<'_>,
645 ) -> Type {
646 match self.resolve_expr_reference(expr_reference) {
647 ResolvedRef::Model(model) => Type::Model(model.id),
648 ResolvedRef::Column(column) => column.ty.clone(),
649 ResolvedRef::Field(field) => field.expr_ty().clone(),
650 ResolvedRef::Cte { .. } => todo!("type inference for CTE columns not implemented"),
651 ResolvedRef::Derived(derived) => {
652 let owner = self.context_at(derived.nesting);
654
655 let query = &*derived.derived.subquery;
656 let cx = owner.scope(query);
657 let column_ty = |row_ty| match row_ty {
658 Type::Record(mut fields) => fields.swap_remove(derived.index),
659 ty => {
660 assert_eq!(derived.index, 0, "scalar derived column index");
661 ty
662 }
663 };
664
665 match &query.body {
666 ExprSet::Values(values) => {
667 if values.is_empty() {
668 return Type::Unknown;
669 }
670 let mut union = TypeUnion::new();
671 for row in &values.rows {
672 union.insert(column_ty(cx.infer_expr_ty2(args, row, false)));
673 }
674 union.simplify()
675 }
676 _ => column_ty(cx.infer_returning_ty2(query.returning_unwrap(), args, true)),
679 }
680 }
681 }
682 }
683}
684
685impl<'a> ExprContext<'a, Schema> {
686 pub fn target_as_model(&self) -> Option<&'a ModelRoot> {
689 self.target.as_model()
690 }
691}
692
693impl<'a, T> Clone for ExprContext<'a, T> {
694 fn clone(&self) -> Self {
695 *self
696 }
697}
698
699impl<'a, T> Copy for ExprContext<'a, T> {}
700
701impl<'a> ResolvedRef<'a> {
702 #[track_caller]
708 pub fn as_column_unwrap(self) -> &'a Column {
709 match self {
710 ResolvedRef::Column(column) => column,
711 _ => panic!("Expected ResolvedRef::Column, found {:?}", self),
712 }
713 }
714
715 #[track_caller]
721 pub fn as_field_unwrap(self) -> &'a Field {
722 match self {
723 ResolvedRef::Field(field) => field,
724 _ => panic!("Expected ResolvedRef::Field, found {:?}", self),
725 }
726 }
727
728 #[track_caller]
734 pub fn as_model_unwrap(self) -> &'a ModelRoot {
735 match self {
736 ResolvedRef::Model(model) => model,
737 _ => panic!("Expected ResolvedRef::Model, found {:?}", self),
738 }
739 }
740}
741
742impl Resolve for Schema {
743 fn model(&self, id: ModelId) -> Option<&Model> {
744 Some(self.app.model(id))
745 }
746
747 fn table(&self, id: TableId) -> Option<&Table> {
748 Some(self.db.table(id))
749 }
750
751 fn table_for_model(&self, model: &ModelRoot) -> Option<&Table> {
752 Some(self.table_for(model.id))
753 }
754}
755
756impl Resolve for crate::schema::app::Schema {
757 fn model(&self, id: ModelId) -> Option<&Model> {
758 self.get_model(id)
759 }
760}
761
762impl Resolve for db::Schema {
763 fn table(&self, id: TableId) -> Option<&Table> {
764 Some(db::Schema::table(self, id))
765 }
766}
767
768impl Resolve for () {}
769
770impl<'a> ExprTarget<'a> {
771 pub fn as_model(self) -> Option<&'a ModelRoot> {
773 match self {
774 ExprTarget::Model(model) => Some(model),
775 _ => None,
776 }
777 }
778
779 #[track_caller]
785 pub fn as_model_unwrap(self) -> &'a ModelRoot {
786 match self.as_model() {
787 Some(model) => model,
788 _ => panic!("expected ExprTarget::Model; was {self:#?}"),
789 }
790 }
791
792 fn model_id(self) -> Option<ModelId> {
794 Some(match self {
795 ExprTarget::Model(model) => model.id,
796 _ => return None,
797 })
798 }
799}
800
801impl<'a, T: Resolve> IntoExprTarget<'a, T> for ExprTarget<'a> {
802 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
803 match self {
804 ExprTarget::Source(source_table) => {
805 if source_table.from.len() == 1 && source_table.from[0].joins.is_empty() {
806 match &source_table.from[0].relation {
807 TableFactor::Table(source_table_id) => {
808 debug_assert_eq!(0, source_table_id.0);
809 debug_assert_eq!(1, source_table.tables.len());
810
811 match &source_table.tables[0] {
812 TableRef::Table(table_id) => {
813 let table = schema.table(*table_id).unwrap();
814 ExprTarget::Table(table)
815 }
816 _ => self,
817 }
818 }
819 }
820 } else {
821 self
822 }
823 }
824 _ => self,
825 }
826 }
827}
828
829impl<'a, T> IntoExprTarget<'a, T> for &'a ModelRoot {
830 fn into_expr_target(self, _schema: &'a T) -> ExprTarget<'a> {
831 ExprTarget::Model(self)
832 }
833}
834
835impl<'a, T> IntoExprTarget<'a, T> for &'a Table {
836 fn into_expr_target(self, _schema: &'a T) -> ExprTarget<'a> {
837 ExprTarget::Table(self)
838 }
839}
840
841impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Query {
842 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
843 self.body.into_expr_target(schema)
844 }
845}
846
847impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a ExprSet {
848 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
849 match self {
850 ExprSet::Select(select) => select.into_expr_target(schema),
851 ExprSet::SetOp(_) => todo!(),
852 ExprSet::Update(update) => update.into_expr_target(schema),
853 ExprSet::Delete(delete) => delete.into_expr_target(schema),
854 ExprSet::Values(_) => ExprTarget::Free,
855 ExprSet::Insert(insert) => insert.into_expr_target(schema),
856 }
857 }
858}
859
860impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Select {
861 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
862 self.source.into_expr_target(schema)
863 }
864}
865
866impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Insert {
867 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
868 self.target.into_expr_target(schema)
869 }
870}
871
872impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Update {
873 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
874 self.target.into_expr_target(schema)
875 }
876}
877
878impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Delete {
879 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
880 self.from.into_expr_target(schema)
881 }
882}
883
884impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a InsertTarget {
885 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
886 match self {
887 InsertTarget::Scope(query) => query.into_expr_target(schema),
888 InsertTarget::Model(model) => {
889 let Some(model) = schema.model(*model) else {
890 todo!()
891 };
892 ExprTarget::Model(model.as_root_unwrap())
893 }
894 InsertTarget::Table(insert_table) => {
895 let table = schema.table(insert_table.table).unwrap();
896 ExprTarget::Table(table)
897 }
898 }
899 }
900}
901
902impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a UpdateTarget {
903 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
904 match self {
905 UpdateTarget::Query(query) => query.into_expr_target(schema),
906 UpdateTarget::Model(model) => {
907 let Some(model) = schema.model(*model) else {
908 todo!()
909 };
910 ExprTarget::Model(model.as_root_unwrap())
911 }
912 UpdateTarget::Table(table_id) => {
913 let Some(table) = schema.table(*table_id) else {
914 todo!()
915 };
916 ExprTarget::Table(table)
917 }
918 }
919 }
920}
921
922impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Source {
923 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
924 match self {
925 Source::Model(source_model) => {
926 let Some(model) = schema.model(source_model.id) else {
927 todo!()
928 };
929 ExprTarget::Model(model.as_root_unwrap())
930 }
931 Source::Table(source_table) => {
932 ExprTarget::Source(source_table).into_expr_target(schema)
933 }
934 }
935 }
936}
937
938impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Statement {
939 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
940 match self {
941 Statement::Delete(stmt) => stmt.into_expr_target(schema),
942 Statement::Insert(stmt) => stmt.into_expr_target(schema),
943 Statement::Query(stmt) => stmt.into_expr_target(schema),
944 Statement::Update(stmt) => stmt.into_expr_target(schema),
945 }
946 }
947}
948
949impl<'a> ArgTyStack<'a> {
950 fn new(tys: &'a [Type]) -> ArgTyStack<'a> {
951 ArgTyStack { tys, parent: None }
952 }
953
954 fn resolve_arg_ty(&self, expr_arg: &ExprArg) -> &'a Type {
955 let mut nesting = expr_arg.nesting;
956 let mut args = self;
957
958 while nesting > 0 {
959 args = args.parent.unwrap();
960 nesting -= 1;
961 }
962
963 &args.tys[expr_arg.position]
964 }
965
966 fn scope<'child>(&'child self, tys: &'child [Type]) -> ArgTyStack<'child> {
967 ArgTyStack {
968 tys,
969 parent: Some(self),
970 }
971 }
972}