1#![recursion_limit = "256"]
24
25pub mod query;
26pub mod types;
27
28pub use query::executor::core::{OperatorStats, ProfileOutput};
29pub use query::executor::procedure::{
30 ProcedureOutput, ProcedureParam, ProcedureRegistry, ProcedureValueType, RegisteredProcedure,
31};
32pub use query::executor::{Executor, ResultNormalizer};
33pub use query::planner::{CostEstimates, ExplainOutput, IndexUsage, LogicalPlan, QueryPlanner};
34pub use types::{
35 Edge, ExecuteResult, FromValue, Node, Path, QueryCursor, QueryResult, QueryWarning, Row, Value,
36};
37pub use uni_cypher::ast::{Query as CypherQuery, TimeTravelSpec};
38
39pub fn validate_read_only(query: &CypherQuery) -> Result<(), String> {
50 use uni_cypher::ast::{Clause, Query, Statement};
51
52 fn check_statement(stmt: &Statement) -> Result<(), String> {
53 for clause in &stmt.clauses {
54 match clause {
55 Clause::Create(_)
56 | Clause::Merge(_)
57 | Clause::Delete(_)
58 | Clause::Set(_)
59 | Clause::Remove(_) => {
60 return Err(
61 "Write clauses (CREATE, MERGE, DELETE, SET, REMOVE) are not allowed \
62 with VERSION AS OF / TIMESTAMP AS OF"
63 .to_string(),
64 );
65 }
66 _ => {}
67 }
68 }
69 Ok(())
70 }
71
72 fn check_query(q: &Query) -> Result<(), String> {
73 match q {
74 Query::Single(stmt) => check_statement(stmt),
75 Query::Union { left, right, .. } => {
76 check_query(left)?;
77 check_query(right)
78 }
79 Query::Explain(inner) => check_query(inner),
80 Query::TimeTravel { query, .. } => check_query(query),
81 Query::Schema(_) | Query::Transaction(_) => {
82 Err("Schema and transaction commands are not allowed \
83 with VERSION AS OF / TIMESTAMP AS OF"
84 .to_string())
85 }
86 }
87 }
88
89 check_query(query)
90}