reddb_engine/query/
labels.rs1use reddb_rql::ast::{FieldRef, Projection};
4
5pub fn projection_name(projection: &Projection) -> String {
6 match projection {
7 Projection::All => "*".to_string(),
8 Projection::Column(column) => column.clone(),
9 Projection::Alias(_, alias) => alias.clone(),
10 Projection::Function(name, args) => {
15 if let Some((_, alias)) = name.split_once(':') {
16 alias.to_string()
17 } else {
18 render_projection_label(name, args)
22 }
23 }
24 Projection::Expression(_, alias) => alias.clone().unwrap_or_else(|| "expr".to_string()),
25 Projection::Field(field, alias) => alias.clone().unwrap_or_else(|| field_ref_name(field)),
26 Projection::Window { name, alias, .. } => alias.clone().unwrap_or_else(|| name.clone()),
27 }
28}
29
30fn projection_operator_symbol(name: &str) -> Option<&'static str> {
33 match name {
34 "ADD" => Some("+"),
35 "SUB" => Some("-"),
36 "MUL" => Some("*"),
37 "DIV" => Some("/"),
38 "MOD" => Some("%"),
39 "CONCAT" => Some("||"),
40 _ => None,
41 }
42}
43
44fn projection_arg_label(projection: &Projection) -> String {
47 match projection {
48 Projection::Column(column) => match column.strip_prefix("LIT:") {
49 Some(lit)
52 if lit.is_empty()
53 || lit.parse::<f64>().is_ok()
54 || lit.eq_ignore_ascii_case("true")
55 || lit.eq_ignore_ascii_case("false")
56 || lit.eq_ignore_ascii_case("null") =>
57 {
58 lit.to_string()
59 }
60 Some(lit) => format!("'{lit}'"),
61 None => column.clone(),
62 },
63 Projection::Function(name, args) => {
64 let base = name.split_once(':').map(|(b, _)| b).unwrap_or(name);
65 render_projection_label(base, args)
66 }
67 Projection::Field(field, _) => field_ref_name(field),
68 Projection::Alias(_, alias) => alias.clone(),
69 other => projection_name(other),
70 }
71}
72
73fn render_projection_label(name: &str, args: &[Projection]) -> String {
77 if let Some(symbol) = projection_operator_symbol(name) {
78 args.iter()
79 .map(projection_arg_label)
80 .collect::<Vec<_>>()
81 .join(&format!(" {symbol} "))
82 } else {
83 format!(
84 "{}({})",
85 name,
86 args.iter()
87 .map(projection_arg_label)
88 .collect::<Vec<_>>()
89 .join(", ")
90 )
91 }
92}
93
94pub fn field_ref_name(field: &FieldRef) -> String {
95 match field {
96 FieldRef::TableColumn { table, column } => {
97 if table.is_empty() {
98 column.clone()
99 } else {
100 format!("{table}.{column}")
101 }
102 }
103 FieldRef::NodeProperty { alias, property } => format!("{alias}.{property}"),
104 FieldRef::EdgeProperty { alias, property } => format!("{alias}.{property}"),
105 FieldRef::NodeId { alias } => format!("{alias}.id"),
106 }
107}