@@ -19,6 +19,7 @@ use spacetimedb_sats::algebraic_type::fmt::fmt_algebraic_type;
1919use spacetimedb_sats:: algebraic_value:: ser:: ValueSerializer ;
2020use spacetimedb_schema:: schema:: ColumnSchema ;
2121use spacetimedb_sql_parser:: ast:: { self , BinOp , ProjectElem , SqlExpr , SqlIdent , SqlLiteral } ;
22+ use spacetimedb_sql_parser:: parser:: recursion;
2223
2324pub mod check;
2425pub mod errors;
@@ -30,7 +31,7 @@ pub mod statement;
3031pub ( crate ) fn type_select ( input : RelExpr , expr : SqlExpr , vars : & Relvars ) -> TypingResult < RelExpr > {
3132 Ok ( RelExpr :: Select (
3233 Box :: new ( input) ,
33- type_expr ( vars, expr, Some ( & AlgebraicType :: Bool ) ) ?,
34+ type_expr ( vars, expr, Some ( & AlgebraicType :: Bool ) , & mut 0 ) ?,
3435 ) )
3536}
3637
@@ -68,7 +69,7 @@ pub(crate) fn type_proj(input: RelExpr, proj: ast::Project, vars: &Relvars) -> T
6869 return Err ( DuplicateName ( alias. into_string ( ) ) . into ( ) ) ;
6970 }
7071
71- if let Expr :: Field ( p) = type_expr ( vars, expr. into ( ) , None ) ? {
72+ if let Expr :: Field ( p) = type_expr ( vars, expr. into ( ) , None , & mut 0 ) ? {
7273 projections. push ( ( alias, p) ) ;
7374 }
7475 }
@@ -79,7 +80,14 @@ pub(crate) fn type_proj(input: RelExpr, proj: ast::Project, vars: &Relvars) -> T
7980}
8081
8182/// Type check and lower a [SqlExpr] into a logical [Expr].
82- pub ( crate ) fn type_expr ( vars : & Relvars , expr : SqlExpr , expected : Option < & AlgebraicType > ) -> TypingResult < Expr > {
83+ pub ( crate ) fn type_expr (
84+ vars : & Relvars ,
85+ expr : SqlExpr ,
86+ expected : Option < & AlgebraicType > ,
87+ depth : & mut usize ,
88+ ) -> TypingResult < Expr > {
89+ recursion:: guard ( depth, recursion:: MAX_RECURSION_TYP_EXPR , "expr::type_expr" ) ?;
90+
8391 match ( expr, expected) {
8492 ( SqlExpr :: Lit ( SqlLiteral :: Bool ( v) ) , None | Some ( AlgebraicType :: Bool ) ) => Ok ( Expr :: bool ( v) ) ,
8593 ( SqlExpr :: Lit ( SqlLiteral :: Bool ( _) ) , Some ( ty) ) => Err ( UnexpectedType :: new ( & AlgebraicType :: Bool , ty) . into ( ) ) ,
@@ -117,21 +125,21 @@ pub(crate) fn type_expr(vars: &Relvars, expr: SqlExpr, expected: Option<&Algebra
117125 } ) )
118126 }
119127 ( SqlExpr :: Log ( a, b, op) , None | Some ( AlgebraicType :: Bool ) ) => {
120- let a = type_expr ( vars, * a, Some ( & AlgebraicType :: Bool ) ) ?;
121- let b = type_expr ( vars, * b, Some ( & AlgebraicType :: Bool ) ) ?;
128+ let a = type_expr ( vars, * a, Some ( & AlgebraicType :: Bool ) , depth ) ?;
129+ let b = type_expr ( vars, * b, Some ( & AlgebraicType :: Bool ) , depth ) ?;
122130 Ok ( Expr :: LogOp ( op, Box :: new ( a) , Box :: new ( b) ) )
123131 }
124132 ( SqlExpr :: Bin ( a, b, op) , None | Some ( AlgebraicType :: Bool ) ) if matches ! ( & * a, SqlExpr :: Lit ( _) ) => {
125- let b = type_expr ( vars, * b, None ) ?;
126- let a = type_expr ( vars, * a, Some ( b. ty ( ) ) ) ?;
133+ let b = type_expr ( vars, * b, None , depth ) ?;
134+ let a = type_expr ( vars, * a, Some ( b. ty ( ) ) , depth ) ?;
127135 if !op_supports_type ( op, a. ty ( ) ) {
128136 return Err ( InvalidOp :: new ( op, a. ty ( ) ) . into ( ) ) ;
129137 }
130138 Ok ( Expr :: BinOp ( op, Box :: new ( a) , Box :: new ( b) ) )
131139 }
132140 ( SqlExpr :: Bin ( a, b, op) , None | Some ( AlgebraicType :: Bool ) ) => {
133- let a = type_expr ( vars, * a, None ) ?;
134- let b = type_expr ( vars, * b, Some ( a. ty ( ) ) ) ?;
141+ let a = type_expr ( vars, * a, None , depth ) ?;
142+ let b = type_expr ( vars, * b, Some ( a. ty ( ) ) , depth ) ?;
135143 if !op_supports_type ( op, a. ty ( ) ) {
136144 return Err ( InvalidOp :: new ( op, a. ty ( ) ) . into ( ) ) ;
137145 }
0 commit comments