Skip to main content

uni_query/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2024-2026 Dragonscale Team
3
4#![recursion_limit = "256"]
5
6pub mod query;
7pub mod types;
8
9pub use query::executor::core::{OperatorStats, ProfileOutput};
10pub use query::executor::procedure::{
11    ProcedureOutput, ProcedureParam, ProcedureRegistry, ProcedureValueType, RegisteredProcedure,
12};
13pub use query::executor::{Executor, ResultNormalizer};
14pub use query::planner::{CostEstimates, ExplainOutput, IndexUsage, LogicalPlan, QueryPlanner};
15pub use types::{Edge, ExecuteResult, FromValue, Node, Path, QueryCursor, QueryResult, Row, Value};
16pub use uni_cypher::ast::{Query as CypherQuery, TimeTravelSpec};
17
18/// Validate that a query AST is read-only (no CREATE, SET, DELETE, MERGE, REMOVE).
19///
20/// Returns `Ok(())` if the query contains only read clauses, or an error
21/// message describing the violation.
22pub fn validate_read_only(query: &CypherQuery) -> Result<(), String> {
23    use uni_cypher::ast::{Clause, Query, Statement};
24
25    fn check_statement(stmt: &Statement) -> Result<(), String> {
26        for clause in &stmt.clauses {
27            match clause {
28                Clause::Create(_)
29                | Clause::Merge(_)
30                | Clause::Delete(_)
31                | Clause::Set(_)
32                | Clause::Remove(_) => {
33                    return Err(
34                        "Write clauses (CREATE, MERGE, DELETE, SET, REMOVE) are not allowed \
35                         with VERSION AS OF / TIMESTAMP AS OF"
36                            .to_string(),
37                    );
38                }
39                _ => {}
40            }
41        }
42        Ok(())
43    }
44
45    fn check_query(q: &Query) -> Result<(), String> {
46        match q {
47            Query::Single(stmt) => check_statement(stmt),
48            Query::Union { left, right, .. } => {
49                check_query(left)?;
50                check_query(right)
51            }
52            Query::Explain(inner) => check_query(inner),
53            Query::TimeTravel { query, .. } => check_query(query),
54            Query::Schema(_) | Query::Transaction(_) => {
55                Err("Schema and transaction commands are not allowed \
56                 with VERSION AS OF / TIMESTAMP AS OF"
57                    .to_string())
58            }
59        }
60    }
61
62    check_query(query)
63}