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::RowsFrom(_) => todo!(),
374 TableRef::Arg(_) => todo!(),
375 }
376 }
377 ExprReference::Model { .. } => {
378 panic!("Cannot resolve ExprReference::Model in Source::Table context")
379 }
380 ExprReference::Field { .. } => panic!(
381 "Cannot resolve ExprReference::Field in Source::Table context - use ExprReference::Column instead"
382 ),
383 }
384 }
385 }
386 }
387
388 pub fn infer_stmt_ty(&self, stmt: &Statement, args: &[Type]) -> Type {
390 let cx = self.scope(stmt);
391
392 match stmt {
393 Statement::Delete(stmt) => stmt
394 .returning
395 .as_ref()
396 .map(|returning| cx.infer_returning_ty(returning, args, false))
397 .unwrap_or(Type::Unit),
398 Statement::Insert(stmt) => stmt
399 .returning
400 .as_ref()
401 .map(|returning| cx.infer_returning_ty(returning, args, stmt.source.single))
402 .unwrap_or(Type::Unit),
403 Statement::Query(stmt) => match &stmt.body {
404 ExprSet::Select(body) => cx.infer_returning_ty(&body.returning, args, stmt.single),
405 ExprSet::SetOp(_body) => todo!(),
406 ExprSet::Update(_body) => todo!(),
407 ExprSet::Delete(body) => body
408 .returning
409 .as_ref()
410 .map(|returning| cx.infer_returning_ty(returning, args, stmt.single))
411 .unwrap_or(Type::Unit),
412 ExprSet::Values(_body) => todo!(),
413 ExprSet::Insert(body) => body
414 .returning
415 .as_ref()
416 .map(|returning| cx.infer_returning_ty(returning, args, stmt.single))
417 .unwrap_or(Type::Unit),
418 },
419 Statement::Update(stmt) => stmt
420 .returning
421 .as_ref()
422 .map(|returning| cx.infer_returning_ty(returning, args, false))
423 .unwrap_or(Type::Unit),
424 }
425 }
426
427 fn infer_returning_ty(&self, returning: &Returning, args: &[Type], single: bool) -> Type {
428 let arg_ty_stack = ArgTyStack::new(args);
429 self.infer_returning_ty2(returning, &arg_ty_stack, single)
430 }
431
432 fn infer_returning_ty2(
433 &self,
434 returning: &Returning,
435 args: &ArgTyStack<'_>,
436 single: bool,
437 ) -> Type {
438 match returning {
439 Returning::Model { .. } => {
440 let ty = Type::Model(
441 self.target
442 .model_id()
443 .expect("returning `Model` when not in model context"),
444 );
445
446 if single { ty } else { Type::list(ty) }
447 }
448 Returning::Changed => todo!(),
449 Returning::Star => todo!(),
450 Returning::Project(expr) => {
451 let ty = self.infer_expr_ty2(args, expr, false);
452
453 if single { ty } else { Type::list(ty) }
454 }
455 Returning::Expr(expr) => self.infer_expr_ty2(args, expr, true),
456 }
457 }
458
459 pub fn infer_expr_ty(&self, expr: &Expr, args: &[Type]) -> Type {
461 let arg_ty_stack = ArgTyStack::new(args);
462 self.infer_expr_ty2(&arg_ty_stack, expr, false)
463 }
464
465 fn infer_expr_ty2(&self, args: &ArgTyStack<'_>, expr: &Expr, returning_expr: bool) -> Type {
466 match expr {
467 Expr::Arg(e) => args.resolve_arg_ty(e).clone(),
468 Expr::And(_) => Type::Bool,
469 Expr::Any(_) | Expr::AnyOp(_) | Expr::AllOp(_) | Expr::InList(_) => Type::Bool,
470 Expr::BinaryOp(_) => Type::Bool,
471 Expr::Cast(e) => e.ty.clone(),
472 Expr::Reference(expr_ref) => {
473 assert!(
474 !returning_expr,
475 "should have been handled in Expr::Project. Invalid expr?"
476 );
477 self.infer_expr_reference_ty2(expr_ref, args)
478 }
479 Expr::IsNull(_) => Type::Bool,
480 Expr::IsVariant(_) => Type::Bool,
481 Expr::Variant(e) => {
482 let base = self.infer_expr_ty2(args, &e.base, returning_expr);
485 let Type::Model(id) = base else {
486 todo!("variant selection on non-enum type {base:#?}")
487 };
488 assert_eq!(id, e.variant.model, "variant selection on the wrong enum");
489 let Some(Model::EmbeddedEnum(embedded)) = self.schema.model(id) else {
490 todo!("variant selection on non-enum model {id:?}")
491 };
492 Type::Record(
493 embedded
494 .variant_fields(e.variant.index)
495 .iter()
496 .map(|field| field.expr_ty().clone())
497 .collect(),
498 )
499 }
500 Expr::List(e) => {
501 debug_assert!(!e.items.is_empty());
502 Type::list(self.infer_expr_ty2(args, &e.items[0], returning_expr))
503 }
504 Expr::Map(e) => {
505 let base = self.infer_expr_ty2(args, &e.base, returning_expr);
507
508 let Type::List(item) = base else {
510 todo!("error handling; base={base:#?}")
511 };
512
513 let scope_tys = &[*item];
514
515 let args = args.scope(scope_tys);
517
518 let ty = self.infer_expr_ty2(&args, &e.map, returning_expr);
520
521 Type::list(ty)
523 }
524 Expr::Not(_) => Type::Bool,
525 Expr::Or(_) => Type::Bool,
526 Expr::Project(e) => {
527 if returning_expr {
528 match &*e.base {
529 Expr::Arg(expr_arg) => {
530 assert!(e.projection.as_slice().len() == 1);
535 return args.resolve_arg_ty(expr_arg).clone();
536 }
537 Expr::Reference(expr_reference) => {
538 assert!(e.projection.as_slice().len() == 1);
543 return self.infer_expr_reference_ty2(expr_reference, args);
544 }
545 _ => {}
546 }
547 }
548
549 let mut base = self.infer_expr_ty2(args, &e.base, returning_expr);
550
551 for step in e.projection.iter() {
552 base = match base {
553 Type::Record(mut fields) => {
554 std::mem::replace(&mut fields[*step], Type::Null)
555 }
556 Type::Model(id) => match self.schema.model(id) {
563 Some(Model::Root(model)) => model.fields[*step].expr_ty().clone(),
564 Some(Model::EmbeddedStruct(embedded)) => {
565 embedded.fields[*step].expr_ty().clone()
566 }
567 _ => todo!("project into non-embedded model {id:?}"),
568 },
569 Type::List(items) => *items,
570 expr => todo!(
571 "returning_expr={returning_expr:#?}; expr={expr:#?}; project={e:#?}"
572 ),
573 }
574 }
575
576 base
577 }
578 Expr::Record(e) => Type::Record(
579 e.fields
580 .iter()
581 .map(|field| self.infer_expr_ty2(args, field, returning_expr))
582 .collect(),
583 ),
584 Expr::Value(value) | Expr::Static(value) => value.infer_ty(),
585 Expr::Let(expr_let) => {
586 let scope_tys: Vec<_> = expr_let
587 .bindings
588 .iter()
589 .map(|b| self.infer_expr_ty2(args, b, returning_expr))
590 .collect();
591 let args = args.scope(&scope_tys);
592 self.infer_expr_ty2(&args, &expr_let.body, returning_expr)
593 }
594 Expr::Match(expr_match) => {
595 let mut union = TypeUnion::new();
600 for arm in &expr_match.arms {
601 let ty = self.infer_expr_ty2(args, &arm.expr, returning_expr);
602 union.insert(ty);
603 }
604 let else_ty = self.infer_expr_ty2(args, &expr_match.else_expr, returning_expr);
605 union.insert(else_ty);
606 union.simplify()
607 }
608 Expr::Error(_) => Type::Unknown,
612 Expr::Exists(_) => Type::Bool,
613 Expr::Func(ExprFunc::Count(_)) => Type::U64,
614 Expr::Func(ExprFunc::LastInsertId(_)) => Type::I64,
615 Expr::Func(ExprFunc::JsonExtract(func)) => func.ty.clone(),
616 Expr::Incoming(incoming) => match incoming {
617 super::ExprIncoming::Model(model) => Type::Model(*model),
618 super::ExprIncoming::Table(table) => {
619 let table = self.schema.table(*table).unwrap_or_else(|| {
620 panic!("incoming table {table:?} is not present in the schema")
621 });
622 Type::Record(
623 table
624 .columns
625 .iter()
626 .map(|column| column.ty.clone())
627 .collect(),
628 )
629 }
630 },
631 _ => todo!("{expr:#?}"),
632 }
633 }
634
635 pub fn infer_expr_reference_ty(&self, expr_reference: &ExprReference) -> Type {
640 self.infer_expr_reference_ty2(expr_reference, &ArgTyStack::new(&[]))
641 }
642
643 fn infer_expr_reference_ty2(
644 &self,
645 expr_reference: &ExprReference,
646 args: &ArgTyStack<'_>,
647 ) -> Type {
648 match self.resolve_expr_reference(expr_reference) {
649 ResolvedRef::Model(model) => Type::Model(model.id),
650 ResolvedRef::Column(column) => column.ty.clone(),
651 ResolvedRef::Field(field) => field.expr_ty().clone(),
652 ResolvedRef::Cte { .. } => todo!("type inference for CTE columns not implemented"),
653 ResolvedRef::Derived(derived) => {
654 let owner = self.context_at(derived.nesting);
656
657 let query = &*derived.derived.subquery;
658 let cx = owner.scope(query);
659 let column_ty = |row_ty| match row_ty {
660 Type::Record(mut fields) => fields.swap_remove(derived.index),
661 ty => {
662 assert_eq!(derived.index, 0, "scalar derived column index");
663 ty
664 }
665 };
666
667 match &query.body {
668 ExprSet::Values(values) => {
669 if values.is_empty() {
670 return Type::Unknown;
671 }
672 let mut union = TypeUnion::new();
673 for row in &values.rows {
674 union.insert(column_ty(cx.infer_expr_ty2(args, row, false)));
675 }
676 union.simplify()
677 }
678 _ => column_ty(cx.infer_returning_ty2(query.returning_unwrap(), args, true)),
681 }
682 }
683 }
684 }
685}
686
687impl<'a> ExprContext<'a, Schema> {
688 pub fn target_as_model(&self) -> Option<&'a ModelRoot> {
691 self.target.as_model()
692 }
693}
694
695impl<'a, T> Clone for ExprContext<'a, T> {
696 fn clone(&self) -> Self {
697 *self
698 }
699}
700
701impl<'a, T> Copy for ExprContext<'a, T> {}
702
703impl<'a> ResolvedRef<'a> {
704 #[track_caller]
710 pub fn as_column_unwrap(self) -> &'a Column {
711 match self {
712 ResolvedRef::Column(column) => column,
713 _ => panic!("Expected ResolvedRef::Column, found {:?}", self),
714 }
715 }
716
717 #[track_caller]
723 pub fn as_field_unwrap(self) -> &'a Field {
724 match self {
725 ResolvedRef::Field(field) => field,
726 _ => panic!("Expected ResolvedRef::Field, found {:?}", self),
727 }
728 }
729
730 #[track_caller]
736 pub fn as_model_unwrap(self) -> &'a ModelRoot {
737 match self {
738 ResolvedRef::Model(model) => model,
739 _ => panic!("Expected ResolvedRef::Model, found {:?}", self),
740 }
741 }
742}
743
744impl Resolve for Schema {
745 fn model(&self, id: ModelId) -> Option<&Model> {
746 Some(self.app.model(id))
747 }
748
749 fn table(&self, id: TableId) -> Option<&Table> {
750 Some(self.db.table(id))
751 }
752
753 fn table_for_model(&self, model: &ModelRoot) -> Option<&Table> {
754 Some(self.table_for(model.id))
755 }
756}
757
758impl Resolve for crate::schema::app::Schema {
759 fn model(&self, id: ModelId) -> Option<&Model> {
760 self.get_model(id)
761 }
762}
763
764impl Resolve for db::Schema {
765 fn table(&self, id: TableId) -> Option<&Table> {
766 Some(db::Schema::table(self, id))
767 }
768}
769
770impl Resolve for () {}
771
772impl<'a> ExprTarget<'a> {
773 pub fn as_model(self) -> Option<&'a ModelRoot> {
775 match self {
776 ExprTarget::Model(model) => Some(model),
777 _ => None,
778 }
779 }
780
781 #[track_caller]
787 pub fn as_model_unwrap(self) -> &'a ModelRoot {
788 match self.as_model() {
789 Some(model) => model,
790 _ => panic!("expected ExprTarget::Model; was {self:#?}"),
791 }
792 }
793
794 fn model_id(self) -> Option<ModelId> {
796 Some(match self {
797 ExprTarget::Model(model) => model.id,
798 _ => return None,
799 })
800 }
801}
802
803impl<'a, T: Resolve> IntoExprTarget<'a, T> for ExprTarget<'a> {
804 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
805 match self {
806 ExprTarget::Source(source_table) => {
807 if source_table.from.len() == 1 && source_table.from[0].joins.is_empty() {
808 match &source_table.from[0].relation {
809 TableFactor::Table(source_table_id) => {
810 debug_assert_eq!(0, source_table_id.0);
811 debug_assert_eq!(1, source_table.tables.len());
812
813 match &source_table.tables[0] {
814 TableRef::Table(table_id) => {
815 let table = schema.table(*table_id).unwrap();
816 ExprTarget::Table(table)
817 }
818 _ => self,
819 }
820 }
821 }
822 } else {
823 self
824 }
825 }
826 _ => self,
827 }
828 }
829}
830
831impl<'a, T> IntoExprTarget<'a, T> for &'a ModelRoot {
832 fn into_expr_target(self, _schema: &'a T) -> ExprTarget<'a> {
833 ExprTarget::Model(self)
834 }
835}
836
837impl<'a, T> IntoExprTarget<'a, T> for &'a Table {
838 fn into_expr_target(self, _schema: &'a T) -> ExprTarget<'a> {
839 ExprTarget::Table(self)
840 }
841}
842
843impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Query {
844 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
845 self.body.into_expr_target(schema)
846 }
847}
848
849impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a ExprSet {
850 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
851 match self {
852 ExprSet::Select(select) => select.into_expr_target(schema),
853 ExprSet::SetOp(_) => todo!(),
854 ExprSet::Update(update) => update.into_expr_target(schema),
855 ExprSet::Delete(delete) => delete.into_expr_target(schema),
856 ExprSet::Values(_) => ExprTarget::Free,
857 ExprSet::Insert(insert) => insert.into_expr_target(schema),
858 }
859 }
860}
861
862impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Select {
863 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
864 self.source.into_expr_target(schema)
865 }
866}
867
868impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Insert {
869 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
870 self.target.into_expr_target(schema)
871 }
872}
873
874impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Update {
875 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
876 self.target.into_expr_target(schema)
877 }
878}
879
880impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Delete {
881 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
882 self.from.into_expr_target(schema)
883 }
884}
885
886impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a InsertTarget {
887 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
888 match self {
889 InsertTarget::Scope(query) => query.into_expr_target(schema),
890 InsertTarget::Model(model) => {
891 let Some(model) = schema.model(*model) else {
892 todo!()
893 };
894 ExprTarget::Model(model.as_root_unwrap())
895 }
896 InsertTarget::Table(insert_table) => {
897 let table = schema.table(insert_table.table).unwrap();
898 ExprTarget::Table(table)
899 }
900 }
901 }
902}
903
904impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a UpdateTarget {
905 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
906 match self {
907 UpdateTarget::Query(query) => query.into_expr_target(schema),
908 UpdateTarget::Model(model) => {
909 let Some(model) = schema.model(*model) else {
910 todo!()
911 };
912 ExprTarget::Model(model.as_root_unwrap())
913 }
914 UpdateTarget::Table(table_id) => {
915 let Some(table) = schema.table(*table_id) else {
916 todo!()
917 };
918 ExprTarget::Table(table)
919 }
920 }
921 }
922}
923
924impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Source {
925 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
926 match self {
927 Source::Model(source_model) => {
928 let Some(model) = schema.model(source_model.id) else {
929 todo!()
930 };
931 ExprTarget::Model(model.as_root_unwrap())
932 }
933 Source::Table(source_table) => {
934 ExprTarget::Source(source_table).into_expr_target(schema)
935 }
936 }
937 }
938}
939
940impl<'a, T: Resolve> IntoExprTarget<'a, T> for &'a Statement {
941 fn into_expr_target(self, schema: &'a T) -> ExprTarget<'a> {
942 match self {
943 Statement::Delete(stmt) => stmt.into_expr_target(schema),
944 Statement::Insert(stmt) => stmt.into_expr_target(schema),
945 Statement::Query(stmt) => stmt.into_expr_target(schema),
946 Statement::Update(stmt) => stmt.into_expr_target(schema),
947 }
948 }
949}
950
951impl<'a> ArgTyStack<'a> {
952 fn new(tys: &'a [Type]) -> ArgTyStack<'a> {
953 ArgTyStack { tys, parent: None }
954 }
955
956 fn resolve_arg_ty(&self, expr_arg: &ExprArg) -> &'a Type {
957 let mut nesting = expr_arg.nesting;
958 let mut args = self;
959
960 while nesting > 0 {
961 args = args.parent.unwrap();
962 nesting -= 1;
963 }
964
965 &args.tys[expr_arg.position]
966 }
967
968 fn scope<'child>(&'child self, tys: &'child [Type]) -> ArgTyStack<'child> {
969 ArgTyStack {
970 tys,
971 parent: Some(self),
972 }
973 }
974}