uqa_sql/semantics/
graph_commands.rs1use crate::{semantics::retrieval::expect_evaluated_string, SQLError, ScalarExpr};
10use uqa_core::Value;
11
12pub const AGE_INVALID_PARAMETER_VALUE: &str = "22023";
13pub const AGE_UNDEFINED_SCHEMA: &str = "3F000";
14pub const AGE_DUPLICATE_SCHEMA: &str = "42P06";
15pub const AGE_UNDEFINED_TABLE: &str = "42P01";
16pub const AGE_FEATURE_NOT_SUPPORTED: &str = "0A000";
17pub const AGE_DEPENDENT_OBJECTS_STILL_EXIST: &str = "2BP01";
18
19pub fn age_error(sqlstate: &str, message: impl Into<String>) -> SQLError {
20 SQLError::Routine {
21 sqlstate: sqlstate.to_string(),
22 message: message.into(),
23 }
24}
25
26pub fn eval_age_name_with(
29 expr: &ScalarExpr,
30 null_message: &str,
31 evaluate: &mut dyn FnMut(&ScalarExpr) -> Result<Value, SQLError>,
32) -> Result<String, SQLError> {
33 match evaluate(expr)? {
34 Value::Null => Err(age_error(AGE_INVALID_PARAMETER_VALUE, null_message)),
35 Value::Str(s) | Value::FixedChar(s) => Ok(s),
36 other => Err(SQLError::TypeMismatch(format!(
37 "graph name must be a string, got {other:?}"
38 ))),
39 }
40}
41
42pub fn eval_age_graph_name_with(
43 expr: &ScalarExpr,
44 evaluate: &mut dyn FnMut(&ScalarExpr) -> Result<Value, SQLError>,
45) -> Result<String, SQLError> {
46 eval_age_name_with(expr, "graph name can not be NULL", evaluate)
47}
48
49pub fn eval_age_bool_with(
50 expr: &ScalarExpr,
51 argument: &str,
52 evaluate: &mut dyn FnMut(&ScalarExpr) -> Result<Value, SQLError>,
53) -> Result<bool, SQLError> {
54 match evaluate(expr)? {
55 Value::Bool(value) => Ok(value),
56 other => Err(SQLError::TypeMismatch(format!(
57 "{argument} must be a boolean, got {other:?}"
58 ))),
59 }
60}
61
62pub fn require_age_arity(
63 name: &str,
64 args: &[ScalarExpr],
65 range: std::ops::RangeInclusive<usize>,
66) -> Result<(), SQLError> {
67 if range.contains(&args.len()) {
68 return Ok(());
69 }
70 let expected = if range.start() == range.end() {
71 range.start().to_string()
72 } else {
73 format!("{} or {}", range.start(), range.end())
74 };
75 Err(SQLError::BadArity {
76 name: name.into(),
77 expected,
78 actual: args.len(),
79 })
80}
81
82pub fn graph_create_name(
83 args: &[ScalarExpr],
84 evaluate: &mut dyn FnMut(&ScalarExpr) -> Result<Value, SQLError>,
85) -> Result<String, SQLError> {
86 if args.len() != 1 {
87 return Err(SQLError::BadArity {
88 name: "graph_create".into(),
89 expected: "1".into(),
90 actual: args.len(),
91 });
92 }
93 expect_evaluated_string(evaluate(&args[0])?, "graph_create.name")
94}
95
96pub fn graph_drop_name(
97 args: &[ScalarExpr],
98 evaluate: &mut dyn FnMut(&ScalarExpr) -> Result<Value, SQLError>,
99) -> Result<String, SQLError> {
100 if !(1..=2).contains(&args.len()) {
101 return Err(SQLError::BadArity {
102 name: "graph_drop".into(),
103 expected: "1 or 2".into(),
104 actual: args.len(),
105 });
106 }
107 expect_evaluated_string(evaluate(&args[0])?, "graph_drop.name")
108}
109
110pub fn validate_graph_drop_cascade(
112 name: &str,
113 graph_exists: bool,
114 cascade_expr: Option<&ScalarExpr>,
115 evaluate: &mut dyn FnMut(&ScalarExpr) -> Result<Value, SQLError>,
116) -> Result<(), SQLError> {
117 if let Some(cascade_expr) = cascade_expr {
118 match evaluate(cascade_expr)? {
119 Value::Bool(false) if graph_exists => {
120 return Err(SQLError::Unsupported(format!(
121 "cannot drop graph {name:?} without cascade"
122 )));
123 }
124 Value::Bool(_) => {}
125 other => {
126 return Err(SQLError::TypeMismatch(format!(
127 "graph_drop.cascade must be a boolean, got {other:?}"
128 )));
129 }
130 }
131 }
132 Ok(())
133}