(expr: &SqlExpr)
| 398 | ]; |
| 399 | |
| 400 | fn validate_deterministic(expr: &SqlExpr) -> Result<(), ExprParseError> { |
| 401 | match expr { |
| 402 | SqlExpr::Function { name, args } => { |
| 403 | if NON_DETERMINISTIC.contains(&name.as_str()) { |
| 404 | return Err(ExprParseError::InvalidLiteral { |
| 405 | detail: format!( |
| 406 | "non-deterministic function '{name}()' not allowed in GENERATED ALWAYS AS" |
| 407 | ), |
| 408 | }); |
| 409 | } |
| 410 | for arg in args { |
| 411 | validate_deterministic(arg)?; |
| 412 | } |
| 413 | Ok(()) |
| 414 | } |
| 415 | SqlExpr::BinaryOp { left, right, .. } => { |
| 416 | validate_deterministic(left)?; |
| 417 | validate_deterministic(right) |
| 418 | } |
| 419 | SqlExpr::Negate(inner) => validate_deterministic(inner), |
| 420 | SqlExpr::Coalesce(args) => { |
| 421 | for arg in args { |
| 422 | validate_deterministic(arg)?; |
| 423 | } |
| 424 | Ok(()) |
| 425 | } |
| 426 | SqlExpr::Case { |
| 427 | operand, |
| 428 | when_thens, |
| 429 | else_expr, |
| 430 | } => { |
| 431 | if let Some(op) = operand { |
| 432 | validate_deterministic(op)?; |
| 433 | } |
| 434 | for (cond, then) in when_thens { |
| 435 | validate_deterministic(cond)?; |
| 436 | validate_deterministic(then)?; |
| 437 | } |
| 438 | if let Some(e) = else_expr { |
| 439 | validate_deterministic(e)?; |
| 440 | } |
| 441 | Ok(()) |
| 442 | } |
| 443 | SqlExpr::Cast { expr, .. } => validate_deterministic(expr), |
| 444 | SqlExpr::NullIf(a, b) => { |
| 445 | validate_deterministic(a)?; |
| 446 | validate_deterministic(b) |
| 447 | } |
| 448 | SqlExpr::IsNull { expr, .. } => validate_deterministic(expr), |
| 449 | SqlExpr::Column(_) |
| 450 | | SqlExpr::Literal(_) |
| 451 | | SqlExpr::OldColumn(_) |
| 452 | | SqlExpr::ExcludedColumn(_) => Ok(()), |
| 453 | } |
| 454 | } |
| 455 | |
| 456 | pub(crate) fn collect_columns(expr: &SqlExpr, deps: &mut Vec<String>) { |
| 457 | match expr { |
no test coverage detected