pgx_utils/sql_entity_graph/metadata/
sql_translatable.rs1use std::error::Error;
10
11use super::return_variant::ReturnsError;
12use super::{FunctionMetadataTypeEntity, Returns};
13
14#[derive(Clone, Copy, Debug, Hash, Ord, PartialOrd, PartialEq, Eq)]
15pub enum ArgumentError {
16 SetOf,
17 Table,
18 BareU8,
19 SkipInArray,
20 Datum,
21}
22
23impl std::fmt::Display for ArgumentError {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 match self {
26 ArgumentError::SetOf => {
27 write!(f, "Cannot use SetOfIterator as an argument")
28 }
29 ArgumentError::Table => {
30 write!(f, "Cannot use TableIterator as an argument")
31 }
32 ArgumentError::BareU8 => {
33 write!(f, "Cannot use bare u8")
34 }
35 ArgumentError::SkipInArray => {
36 write!(f, "SqlMapping::Skip inside Array is not valid")
37 }
38 ArgumentError::Datum => {
39 write!(f, "A Datum as an argument means that `sql = \"...\"` must be set in the declaration")
40 }
41 }
42 }
43}
44
45#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
47pub enum SqlMapping {
48 As(String),
50 Composite {
51 array_brackets: bool,
52 },
53 Source {
55 array_brackets: bool,
56 },
57 Skip,
59}
60
61impl SqlMapping {
62 pub fn literal(s: &'static str) -> SqlMapping {
63 SqlMapping::As(String::from(s))
64 }
65}
66
67impl Error for ArgumentError {}
68
69pub unsafe trait SqlTranslatable {
83 fn type_name() -> &'static str {
84 core::any::type_name::<Self>()
85 }
86 fn argument_sql() -> Result<SqlMapping, ArgumentError>;
87 fn return_sql() -> Result<Returns, ReturnsError>;
88 fn variadic() -> bool {
89 false
90 }
91 fn optional() -> bool {
92 false
93 }
94 fn entity() -> FunctionMetadataTypeEntity {
95 FunctionMetadataTypeEntity {
96 type_name: Self::type_name(),
97 argument_sql: Self::argument_sql(),
98 return_sql: Self::return_sql(),
99 variadic: Self::variadic(),
100 optional: Self::optional(),
101 }
102 }
103}
104
105unsafe impl<T> SqlTranslatable for Option<T>
106where
107 T: SqlTranslatable,
108{
109 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
110 T::argument_sql()
111 }
112 fn return_sql() -> Result<Returns, ReturnsError> {
113 T::return_sql()
114 }
115 fn optional() -> bool {
116 true
117 }
118}
119
120unsafe impl<T> SqlTranslatable for *mut T
121where
122 T: SqlTranslatable,
123{
124 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
125 T::argument_sql()
126 }
127 fn return_sql() -> Result<Returns, ReturnsError> {
128 T::return_sql()
129 }
130 fn optional() -> bool {
131 T::optional()
132 }
133}
134
135unsafe impl<T, E> SqlTranslatable for Result<T, E>
136where
137 T: SqlTranslatable,
138 E: std::error::Error + 'static,
139{
140 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
141 T::argument_sql()
142 }
143 fn return_sql() -> Result<Returns, ReturnsError> {
144 T::return_sql()
145 }
146 fn optional() -> bool {
147 true
148 }
149}
150
151unsafe impl<T> SqlTranslatable for Vec<T>
152where
153 T: SqlTranslatable,
154{
155 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
156 match T::type_name() {
157 id if id == u8::type_name() => Ok(SqlMapping::As(format!("bytea"))),
158 _ => match T::argument_sql() {
159 Ok(SqlMapping::As(val)) => Ok(SqlMapping::As(format!("{val}[]"))),
160 Ok(SqlMapping::Composite { array_brackets: _ }) => {
161 Ok(SqlMapping::Composite { array_brackets: true })
162 }
163 Ok(SqlMapping::Source { array_brackets: _ }) => {
164 Ok(SqlMapping::Source { array_brackets: true })
165 }
166 Ok(SqlMapping::Skip) => Ok(SqlMapping::Skip),
167 err @ Err(_) => err,
168 },
169 }
170 }
171 fn return_sql() -> Result<Returns, ReturnsError> {
172 match T::type_name() {
173 id if id == u8::type_name() => Ok(Returns::One(SqlMapping::As(format!("bytea")))),
174 _ => match T::return_sql() {
175 Ok(Returns::One(SqlMapping::As(val))) => {
176 Ok(Returns::One(SqlMapping::As(format!("{val}[]"))))
177 }
178 Ok(Returns::One(SqlMapping::Composite { array_brackets: _ })) => {
179 Ok(Returns::One(SqlMapping::Composite { array_brackets: true }))
180 }
181 Ok(Returns::One(SqlMapping::Source { array_brackets: _ })) => {
182 Ok(Returns::One(SqlMapping::Source { array_brackets: true }))
183 }
184 Ok(Returns::One(SqlMapping::Skip)) => Ok(Returns::One(SqlMapping::Skip)),
185 Ok(Returns::SetOf(_)) => Err(ReturnsError::SetOfInArray),
186 Ok(Returns::Table(_)) => Err(ReturnsError::TableInArray),
187 err @ Err(_) => err,
188 },
189 }
190 }
191 fn optional() -> bool {
192 T::optional()
193 }
194}
195
196unsafe impl SqlTranslatable for u8 {
197 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
198 Err(ArgumentError::BareU8)
199 }
200 fn return_sql() -> Result<Returns, ReturnsError> {
201 Err(ReturnsError::BareU8)
202 }
203}
204
205unsafe impl SqlTranslatable for i32 {
206 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
207 Ok(SqlMapping::literal("INT"))
208 }
209 fn return_sql() -> Result<Returns, ReturnsError> {
210 Ok(Returns::One(SqlMapping::literal("INT")))
211 }
212}
213
214unsafe impl SqlTranslatable for u32 {
215 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
216 Ok(SqlMapping::Source { array_brackets: false })
217 }
218 fn return_sql() -> Result<Returns, ReturnsError> {
219 Ok(Returns::One(SqlMapping::Source { array_brackets: false }))
220 }
221}
222
223unsafe impl SqlTranslatable for String {
224 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
225 Ok(SqlMapping::literal("TEXT"))
226 }
227 fn return_sql() -> Result<Returns, ReturnsError> {
228 Ok(Returns::One(SqlMapping::literal("TEXT")))
229 }
230}
231
232unsafe impl<T> SqlTranslatable for &T
233where
234 T: SqlTranslatable,
235{
236 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
237 T::argument_sql()
238 }
239 fn return_sql() -> Result<Returns, ReturnsError> {
240 T::return_sql()
241 }
242}
243
244unsafe impl<'a> SqlTranslatable for &'a str {
245 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
246 Ok(SqlMapping::literal("TEXT"))
247 }
248 fn return_sql() -> Result<Returns, ReturnsError> {
249 Ok(Returns::One(SqlMapping::literal("TEXT")))
250 }
251}
252
253unsafe impl<'a> SqlTranslatable for &'a [u8] {
254 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
255 Ok(SqlMapping::literal("bytea"))
256 }
257 fn return_sql() -> Result<Returns, ReturnsError> {
258 Ok(Returns::One(SqlMapping::literal("bytea")))
259 }
260}
261
262unsafe impl SqlTranslatable for i8 {
263 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
264 Ok(SqlMapping::As(String::from("\"char\"")))
265 }
266 fn return_sql() -> Result<Returns, ReturnsError> {
267 Ok(Returns::One(SqlMapping::As(String::from("\"char\""))))
268 }
269}
270
271unsafe impl SqlTranslatable for i16 {
272 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
273 Ok(SqlMapping::literal("smallint"))
274 }
275 fn return_sql() -> Result<Returns, ReturnsError> {
276 Ok(Returns::One(SqlMapping::literal("smallint")))
277 }
278}
279
280unsafe impl SqlTranslatable for i64 {
281 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
282 Ok(SqlMapping::literal("bigint"))
283 }
284 fn return_sql() -> Result<Returns, ReturnsError> {
285 Ok(Returns::One(SqlMapping::literal("bigint")))
286 }
287}
288
289unsafe impl SqlTranslatable for bool {
290 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
291 Ok(SqlMapping::literal("bool"))
292 }
293 fn return_sql() -> Result<Returns, ReturnsError> {
294 Ok(Returns::One(SqlMapping::literal("bool")))
295 }
296}
297
298unsafe impl SqlTranslatable for char {
299 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
300 Ok(SqlMapping::literal("varchar"))
301 }
302 fn return_sql() -> Result<Returns, ReturnsError> {
303 Ok(Returns::One(SqlMapping::literal("varchar")))
304 }
305}
306
307unsafe impl SqlTranslatable for f32 {
308 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
309 Ok(SqlMapping::literal("real"))
310 }
311 fn return_sql() -> Result<Returns, ReturnsError> {
312 Ok(Returns::One(SqlMapping::literal("real")))
313 }
314}
315
316unsafe impl SqlTranslatable for f64 {
317 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
318 Ok(SqlMapping::literal("double precision"))
319 }
320 fn return_sql() -> Result<Returns, ReturnsError> {
321 Ok(Returns::One(SqlMapping::literal("double precision")))
322 }
323}
324
325unsafe impl SqlTranslatable for std::ffi::CStr {
326 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
327 Ok(SqlMapping::literal("cstring"))
328 }
329 fn return_sql() -> Result<Returns, ReturnsError> {
330 Ok(Returns::One(SqlMapping::literal("cstring")))
331 }
332}
333
334unsafe impl SqlTranslatable for &'static std::ffi::CStr {
335 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
336 Ok(SqlMapping::literal("cstring"))
337 }
338 fn return_sql() -> Result<Returns, ReturnsError> {
339 Ok(Returns::One(SqlMapping::literal("cstring")))
340 }
341}
342
343unsafe impl SqlTranslatable for &'static cstr_core::CStr {
344 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
345 Ok(SqlMapping::literal("cstring"))
346 }
347 fn return_sql() -> Result<Returns, ReturnsError> {
348 Ok(Returns::One(SqlMapping::literal("cstring")))
349 }
350}
351
352unsafe impl SqlTranslatable for cstr_core::CStr {
353 fn argument_sql() -> Result<SqlMapping, ArgumentError> {
354 Ok(SqlMapping::literal("cstring"))
355 }
356 fn return_sql() -> Result<Returns, ReturnsError> {
357 Ok(Returns::One(SqlMapping::literal("cstring")))
358 }
359}