uqa_sql/catalog/
json_path.rs1use crate::{ast::FunctionDispatch, ColumnType};
10
11#[derive(Debug, Clone, Copy)]
12pub struct JsonPathFunction {
13 pub name: &'static str,
14 pub oid: i64,
15 pub argument_oids: &'static [i64],
16 pub result_oid: i64,
17 pub jsonb: bool,
18 pub as_text: bool,
19}
20
21pub const JSON_PATH_FUNCTIONS: [JsonPathFunction; 4] = [
22 JsonPathFunction {
23 name: "json_extract_path",
24 oid: 3951,
25 argument_oids: &[114, 1009],
26 result_oid: 114,
27 jsonb: false,
28 as_text: false,
29 },
30 JsonPathFunction {
31 name: "json_extract_path_text",
32 oid: 3953,
33 argument_oids: &[114, 1009],
34 result_oid: 25,
35 jsonb: false,
36 as_text: true,
37 },
38 JsonPathFunction {
39 name: "jsonb_extract_path",
40 oid: 3217,
41 argument_oids: &[3802, 1009],
42 result_oid: 3802,
43 jsonb: true,
44 as_text: false,
45 },
46 JsonPathFunction {
47 name: "jsonb_extract_path_text",
48 oid: 3940,
49 argument_oids: &[3802, 1009],
50 result_oid: 25,
51 jsonb: true,
52 as_text: true,
53 },
54];
55
56impl JsonPathFunction {
57 #[must_use]
58 pub const fn by_oid(oid: i64) -> Option<Self> {
59 let mut index = 0;
60 while index < JSON_PATH_FUNCTIONS.len() {
61 if JSON_PATH_FUNCTIONS[index].oid == oid {
62 return Some(JSON_PATH_FUNCTIONS[index]);
63 }
64 index += 1;
65 }
66 None
67 }
68
69 #[must_use]
70 pub fn lookup(name: &str) -> Option<Self> {
71 JSON_PATH_FUNCTIONS.into_iter().find(|entry| {
72 name.eq_ignore_ascii_case(entry.name)
73 || name
74 .get(..11)
75 .is_some_and(|prefix| prefix.eq_ignore_ascii_case("pg_catalog."))
76 && name[11..].eq_ignore_ascii_case(entry.name)
77 })
78 }
79
80 #[must_use]
81 pub const fn input_type(self) -> ColumnType {
82 if self.jsonb {
83 ColumnType::JsonB
84 } else {
85 ColumnType::Json
86 }
87 }
88
89 #[must_use]
90 pub const fn result_type(self) -> ColumnType {
91 if self.as_text {
92 ColumnType::Text
93 } else {
94 self.input_type()
95 }
96 }
97
98 #[must_use]
99 pub const fn dispatch(self) -> FunctionDispatch {
100 FunctionDispatch::JsonPath {
101 jsonb: self.jsonb,
102 as_text: self.as_text,
103 }
104 }
105}