Skip to main content

uqa_sql/catalog/node_tree/deparse/
relation.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Validate the relation context accepted by `pg_get_expr` before opening that relation.
8
9use super::{Field, SQLError};
10
11pub fn validate_relation(value: &Field, has_relation: bool) -> Result<(), SQLError> {
12    let mut head = value;
13    while let Field::List(items) = head {
14        let Some(first) = items.first() else {
15            return Ok(());
16        };
17        head = first;
18    }
19    if matches!(head, Field::Node(node) if node.kind == "QUERY") {
20        return Err(parameter_error("input is a query, not an expression"));
21    }
22    validate_variables(value, has_relation)
23}
24
25fn validate_variables(value: &Field, has_relation: bool) -> Result<(), SQLError> {
26    match value {
27        Field::Node(node) => {
28            if node.kind == "VAR" && node.integer("varlevelsup")? == 0 {
29                if !has_relation {
30                    return Err(parameter_error("expression contains variables"));
31                }
32                if node.integer("varno")? != 1 {
33                    return Err(parameter_error(
34                        "expression contains variables of more than one relation",
35                    ));
36                }
37            }
38            for (_, field) in &node.fields {
39                validate_variables(field, has_relation)?;
40            }
41        }
42        Field::List(items) => {
43            for item in items {
44                validate_variables(item, has_relation)?;
45            }
46        }
47        _ => {}
48    }
49    Ok(())
50}
51
52fn parameter_error(message: &str) -> SQLError {
53    SQLError::Routine {
54        sqlstate: "22023".into(),
55        message: message.into(),
56    }
57}