uqa_sql/render/
legacy_vector.rs1use crate::SQLError;
10use uqa_core::{LegacyVectorValue, Value};
11
12pub fn legacy_vector_expression(vector: &LegacyVectorValue) -> Result<String, SQLError> {
14 let ty = vector.kind().type_name();
15 if !vector.has_vector_layout() {
16 return Ok(format!("trim_array('0'::{ty}, 1)"));
17 }
18 let text = vector
19 .elements()
20 .iter()
21 .map(|value| {
22 let Value::Int(value) = value else {
23 unreachable!("validated integer vector")
24 };
25 value.to_string()
26 })
27 .collect::<Vec<_>>()
28 .join(" ");
29 let literal = format!("'{text}'::{ty}");
30 match vector.as_array().lower_bounds() {
31 [0] => Ok(literal),
32 [1] if !vector.elements().is_empty() => Ok(format!("trim_array({literal}, 0)")),
33 _ => Err(SQLError::TypeMismatch(
34 "legacy vector lower bounds cannot be represented by an SQL literal".into(),
35 )),
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use uqa_core::{ArrayValue, LegacyVectorKind};
43
44 #[test]
45 fn legacy_vector_expression_round_trip_preserves_dimensions_and_bounds() {
46 for kind in [LegacyVectorKind::SmallInteger, LegacyVectorKind::Oid] {
47 for (elements, bounds) in [
48 (vec![Value::Int(1)], vec![0]),
49 (vec![Value::Int(1)], vec![1]),
50 (vec![], vec![0]),
51 (vec![], vec![]),
52 ] {
53 let vector = LegacyVectorValue::try_from_array(
54 kind,
55 ArrayValue::with_lower_bounds(elements, bounds).unwrap(),
56 )
57 .unwrap();
58 let expression = legacy_vector_expression(&vector).unwrap();
59 let crate::Statement::Select(select) =
60 crate::compile(&format!("SELECT {expression}"))
61 .unwrap()
62 .remove(0)
63 else {
64 panic!("expected SELECT")
65 };
66 let value = crate::expr::eval(
67 &select.projections[0].expr,
68 &crate::expr::EvalContext::new(None, &[]),
69 )
70 .unwrap();
71 let Value::LegacyVector(restored) = value else {
72 panic!("lost vector type")
73 };
74 assert_eq!(restored.kind(), kind);
75 assert_eq!(restored.as_array(), vector.as_array());
76 assert_eq!(
77 crate::catalog::expression_text::schema_expr_text(&crate::ast::Expr::Literal(
78 Value::LegacyVector(vector)
79 )),
80 expression
81 );
82 }
83 }
84 }
85}