Skip to main content

nodedb_sql/planner/defaults/
convert.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Conversion between the evaluator's value type and the planner's literal type.
4
5use crate::error::SqlError;
6use crate::types::SqlValue;
7
8/// Convert an evaluated SQL literal into the engine-facing value type.
9pub(super) fn sql_value_to_ndb(v: SqlValue) -> nodedb_types::Value {
10    match v {
11        SqlValue::Null => nodedb_types::Value::Null,
12        SqlValue::Bool(b) => nodedb_types::Value::Bool(b),
13        SqlValue::Int(i) => nodedb_types::Value::Integer(i),
14        SqlValue::Float(f) => nodedb_types::Value::Float(f),
15        SqlValue::Decimal(d) => nodedb_types::Value::Decimal(d),
16        SqlValue::String(s) => nodedb_types::Value::String(s),
17        SqlValue::Bytes(b) => nodedb_types::Value::Bytes(b),
18        SqlValue::Array(a) => {
19            nodedb_types::Value::Array(a.into_iter().map(sql_value_to_ndb).collect())
20        }
21        SqlValue::Timestamp(dt) => nodedb_types::Value::NaiveDateTime(dt),
22        SqlValue::Timestamptz(dt) => nodedb_types::Value::DateTime(dt),
23    }
24}
25
26/// Convert an evaluated default back into the planner's literal type.
27///
28/// The inverse of `sql_value_to_ndb` above, which is the only producer of
29/// these values — so every shape the evaluator can emit has an exact
30/// counterpart here. Anything else raises rather than rendering through
31/// `Debug`: a `DEFAULT` that stored `Uuid("…")` as its own debug text is the
32/// same class of defect as dropping it, and harder to notice because the
33/// column looks populated.
34pub fn default_value_to_sql(column: &str, value: nodedb_types::Value) -> crate::Result<SqlValue> {
35    Ok(match value {
36        nodedb_types::Value::Null => SqlValue::Null,
37        nodedb_types::Value::Bool(b) => SqlValue::Bool(b),
38        nodedb_types::Value::Integer(i) => SqlValue::Int(i),
39        nodedb_types::Value::Float(f) => SqlValue::Float(f),
40        nodedb_types::Value::Decimal(d) => SqlValue::Decimal(d),
41        nodedb_types::Value::String(s) => SqlValue::String(s),
42        nodedb_types::Value::Bytes(b) => SqlValue::Bytes(b),
43        nodedb_types::Value::NaiveDateTime(dt) => SqlValue::Timestamp(dt),
44        nodedb_types::Value::DateTime(dt) => SqlValue::Timestamptz(dt),
45        nodedb_types::Value::Array(items) => SqlValue::Array(
46            items
47                .into_iter()
48                .map(|item| default_value_to_sql(column, item))
49                .collect::<crate::Result<Vec<_>>>()?,
50        ),
51        other => {
52            return Err(SqlError::Unsupported {
53                detail: format!(
54                    "default for column '{column}' evaluates to a value with no SQL literal \
55                     form: {other:?}"
56                ),
57            });
58        }
59    })
60}