grafbase_sql_ast/ast/function/
json_extract.rs

1use super::Function;
2use crate::ast::{Expression, FunctionType};
3use std::borrow::Cow;
4
5#[derive(Debug, Clone, PartialEq)]
6pub struct JsonExtract<'a> {
7    pub(crate) column: Box<Expression<'a>>,
8    pub(crate) path: JsonPath<'a>,
9    pub(crate) extract_as_string: bool,
10}
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum JsonPath<'a> {
14    #[cfg(feature = "mysql")]
15    String(Cow<'a, str>),
16    #[cfg(feature = "postgresql")]
17    Array(Vec<Cow<'a, str>>),
18}
19
20impl<'a> JsonPath<'a> {
21    #[cfg(feature = "mysql")]
22    pub fn string<S>(string: S) -> JsonPath<'a>
23    where
24        S: Into<Cow<'a, str>>,
25    {
26        JsonPath::String(string.into())
27    }
28
29    #[cfg(feature = "postgresql")]
30    pub fn array<A, V>(array: A) -> JsonPath<'a>
31    where
32        V: Into<Cow<'a, str>>,
33        A: Into<Vec<V>>,
34    {
35        JsonPath::Array(array.into().into_iter().map(|v| v.into()).collect())
36    }
37}
38
39/// Extracts a subset of a JSON blob given a path.
40/// Two types of paths can be used:
41/// - `String` paths, referring to JSON paths. This is supported by MySQL only.
42/// - `Array` paths, supported by Postgres only.
43pub fn json_extract<'a, C, P>(column: C, path: P, extract_as_string: bool) -> Function<'a>
44where
45    C: Into<Expression<'a>>,
46    P: Into<JsonPath<'a>>,
47{
48    let fun = JsonExtract {
49        column: Box::new(column.into()),
50        path: path.into(),
51        extract_as_string,
52    };
53
54    fun.into()
55}
56
57impl<'a> From<JsonExtract<'a>> for Function<'a> {
58    fn from(value: JsonExtract<'a>) -> Self {
59        Self {
60            typ_: FunctionType::JsonExtract(value),
61            alias: None,
62        }
63    }
64}