sea_query/extension/postgres/func/
json_query.rs1use std::borrow::Cow;
2
3use crate::{
4 extension::postgres::{
5 json_fn::{QuotesClause, WrapperClause, write_json_path_expr, write_passing},
6 json_table::OnClause,
7 },
8 *,
9};
10
11#[derive(Debug, Clone)]
13pub struct Builder {
14 context_item: Expr,
15 path_expression: Cow<'static, str>,
16 passing: Vec<(Value, Cow<'static, str>)>,
17 returning: Option<crate::TypeRef>,
18 wrapper: Option<WrapperClause>,
19 quotes: Option<QuotesClause>,
20 on_empty: Option<OnClause>,
21 on_error: Option<OnClause>,
22}
23
24impl From<Builder> for FunctionCall {
25 fn from(builder: Builder) -> Self {
26 builder.build()
27 }
28}
29
30impl From<Builder> for Expr {
31 fn from(builder: Builder) -> Self {
32 Expr::FunctionCall(builder.build())
33 }
34}
35
36impl Builder {
37 pub fn passing<V, A>(mut self, value: V, alias: A) -> Self
38 where
39 V: Into<Value>,
40 A: Into<Cow<'static, str>>,
41 {
42 self.passing.push((value.into(), alias.into()));
43 self
44 }
45
46 pub fn passing_many<V, A, I>(mut self, passing: I) -> Self
48 where
49 V: Into<Value>,
50 A: Into<Cow<'static, str>>,
51 I: IntoIterator<Item = (V, A)>,
52 {
53 for (value, alias) in passing {
54 self.passing.push((value.into(), alias.into()));
55 }
56 self
57 }
58
59 pub fn returning<T>(mut self, returning: T) -> Self
61 where
62 T: Into<TypeRef>,
63 {
64 self.returning = Some(returning.into());
65 self
66 }
67
68 pub fn wrapper<T>(mut self, wrapper: T) -> Self
70 where
71 T: Into<WrapperClause>,
72 {
73 self.wrapper = Some(wrapper.into());
74 self
75 }
76
77 pub fn quotes<T>(mut self, quotes: T) -> Self
79 where
80 T: Into<QuotesClause>,
81 {
82 self.quotes = Some(quotes.into());
83 self
84 }
85
86 pub fn error_on_empty(mut self) -> Self {
87 self.on_empty = Some(OnClause::Error);
88 self
89 }
90
91 pub fn null_on_empty(mut self) -> Self {
92 self.on_empty = Some(OnClause::Null);
93 self
94 }
95
96 pub fn empty_array_on_empty(mut self) -> Self {
97 self.on_empty = Some(OnClause::EmptyArray);
98 self
99 }
100
101 pub fn empty_object_on_empty(mut self) -> Self {
102 self.on_empty = Some(OnClause::EmptyObject);
103 self
104 }
105
106 pub fn default_on_empty<T>(mut self, expr: T) -> Self
107 where
108 T: Into<Expr>,
109 {
110 self.on_empty = Some(OnClause::Default(expr.into()));
111 self
112 }
113
114 pub fn error_on_error(mut self) -> Self {
115 self.on_error = Some(OnClause::Error);
116 self
117 }
118
119 pub fn null_on_error(mut self) -> Self {
120 self.on_error = Some(OnClause::Null);
121 self
122 }
123
124 pub fn empty_array_on_error(mut self) -> Self {
125 self.on_error = Some(OnClause::EmptyArray);
126 self
127 }
128
129 pub fn empty_object_on_error(mut self) -> Self {
130 self.on_error = Some(OnClause::EmptyObject);
131 self
132 }
133
134 pub fn default_on_error<T>(mut self, expr: T) -> Self
135 where
136 T: Into<Expr>,
137 {
138 self.on_error = Some(OnClause::Default(expr.into()));
139 self
140 }
141
142 pub fn build(self) -> FunctionCall {
143 self.build_internal().unwrap()
144 }
145
146 fn build_internal(self) -> Result<FunctionCall, core::fmt::Error> {
147 let mut buf = String::with_capacity(50);
148
149 PostgresQueryBuilder.prepare_expr(&self.context_item, &mut buf);
150 buf.write_str(" ")?;
151 write_json_path_expr(&mut buf, &self.path_expression)?;
152
153 write_passing(&mut buf, self.passing)?;
154
155 if let Some(returning) = self.returning {
157 buf.write_str(" RETURNING ")?;
158 PostgresQueryBuilder.prepare_type_ref(&returning, &mut buf);
159 }
160
161 if let Some(wrapper) = self.wrapper {
162 wrapper.write_to(&mut buf)?;
163 }
164
165 if let Some(quotes) = self.quotes {
166 quotes.write_to(&mut buf)?;
167 }
168
169 if let Some(on_empty) = self.on_empty {
170 buf.write_str(" ")?;
171 on_empty.write_to(&mut buf)?;
172 buf.write_str(" ON EMPTY")?;
173 }
174
175 if let Some(on_error) = self.on_error {
176 buf.write_str(" ")?;
177 on_error.write_to(&mut buf)?;
178 buf.write_str(" ON ERROR")?;
179 }
180
181 Ok(FunctionCall::new(Func::Custom("JSON_QUERY".into())).arg(Expr::Custom(buf.into())))
182 }
183}
184
185impl PgFunc {
186 pub fn json_query<T, P>(context_item: T, path_expression: P) -> Builder
227 where
228 T: Into<Expr>,
229 P: Into<Cow<'static, str>>,
230 {
231 Builder {
232 context_item: context_item.into(),
233 path_expression: path_expression.into(),
234 passing: Vec::new(),
235 returning: None,
236 wrapper: None,
237 quotes: None,
238 on_empty: None,
239 on_error: None,
240 }
241 }
242}