Skip to content

Commit a8f694f

Browse files
authored
chore(query): cast variant to other type allow cast JSON null as SQL NULL (#17412)
* chore(query): cast variant to other type allow cast JSON null as SQL NULL * fix * fix
1 parent 5bd7525 commit a8f694f

File tree

10 files changed

+367
-163
lines changed

10 files changed

+367
-163
lines changed

src/query/expression/src/evaluator.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,34 @@ impl<'a> Evaluator<'a> {
349349
}
350350
_ => unreachable!(),
351351
},
352+
(
353+
DataType::Nullable(box DataType::Variant) | DataType::Variant,
354+
DataType::Nullable(box DataType::Boolean)
355+
| DataType::Nullable(box DataType::Number(_))
356+
| DataType::Nullable(box DataType::String)
357+
| DataType::Nullable(box DataType::Date)
358+
| DataType::Nullable(box DataType::Timestamp),
359+
) => {
360+
// allow cast variant to nullable types.
361+
let inner_dest_ty = dest_type.remove_nullable();
362+
let cast_fn = format!("to_{}", inner_dest_ty.to_string().to_lowercase());
363+
if let Some(new_value) = self.run_simple_cast(
364+
span,
365+
src_type,
366+
dest_type,
367+
value.clone(),
368+
&cast_fn,
369+
validity.clone(),
370+
options,
371+
)? {
372+
Ok(new_value)
373+
} else {
374+
Err(ErrorCode::BadArguments(format!(
375+
"unable to cast type `{src_type}` to type `{dest_type}`"
376+
))
377+
.set_span(span))
378+
}
379+
}
352380
(DataType::Nullable(inner_src_ty), DataType::Nullable(inner_dest_ty)) => match value {
353381
Value::Scalar(Scalar::Null) => Ok(Value::Scalar(Scalar::Null)),
354382
Value::Scalar(_) => {

src/query/expression/src/types.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,31 @@ impl DataType {
114114
}
115115
}
116116

117+
pub fn nest_wrap_nullable(&self) -> Self {
118+
match self {
119+
DataType::Null => self.clone(),
120+
DataType::Nullable(box inner_ty) => inner_ty.nest_wrap_nullable(),
121+
DataType::Array(box inner_ty) => Self::Nullable(Box::new(Self::Array(Box::new(
122+
inner_ty.nest_wrap_nullable(),
123+
)))),
124+
DataType::Map(box DataType::Tuple(inner_tys)) if inner_tys.len() == 2 => {
125+
let key_ty = inner_tys[0].clone();
126+
let val_ty = inner_tys[1].nest_wrap_nullable();
127+
Self::Nullable(Box::new(Self::Map(Box::new(Self::Tuple(vec![
128+
key_ty, val_ty,
129+
])))))
130+
}
131+
DataType::Tuple(inner_tys) => {
132+
let new_inner_tys = inner_tys
133+
.iter()
134+
.map(|inner_ty| inner_ty.nest_wrap_nullable())
135+
.collect();
136+
Self::Nullable(Box::new(Self::Tuple(new_inner_tys)))
137+
}
138+
_ => Self::Nullable(Box::new(self.clone())),
139+
}
140+
}
141+
117142
pub fn is_nullable_or_null(&self) -> bool {
118143
matches!(self, &DataType::Nullable(_) | &DataType::Null)
119144
}

0 commit comments

Comments
 (0)