pgx_utils/sql_entity_graph/metadata/
function_metadata.rs

1/*!
2
3Function level metadata for Rust to SQL translation
4
5> Like all of the [`sql_entity_graph`][crate::sql_entity_graph] APIs, this is considered **internal**
6to the `pgx` framework and very subject to change between versions. While you may use this, please do it with caution.
7
8
9*/
10use super::{FunctionMetadataEntity, PhantomDataExt, SqlTranslatable};
11use core::marker::PhantomData;
12
13/**
14Provide SQL generation related information on functions
15
16```rust
17use pgx_utils::sql_entity_graph::metadata::{FunctionMetadata, Returns, SqlMapping};
18fn floof(i: i32) -> String { todo!() }
19
20type FunctionPointer = fn(i32) -> String;
21let marker: FunctionPointer = floof;
22let metadata = pgx_utils::sql_entity_graph::metadata::FunctionMetadata::entity(&marker);
23assert_eq!(
24    metadata.retval.unwrap().return_sql,
25    Ok(Returns::One(SqlMapping::As("TEXT".to_string()))),
26);
27```
28 */
29pub trait FunctionMetadata<Inputs, Output> {
30    fn path(&self) -> &'static str {
31        core::any::type_name::<Self>()
32    }
33    fn entity(&self) -> FunctionMetadataEntity;
34}
35
36impl<Output> FunctionMetadata<(), Output> for fn() -> Output
37where
38    Output: SqlTranslatable,
39{
40    fn entity(&self) -> FunctionMetadataEntity {
41        FunctionMetadataEntity {
42            arguments: vec![],
43            retval: {
44                let marker: PhantomData<Output> = PhantomData;
45                Some(marker.entity())
46            },
47            path: self.path(),
48        }
49    }
50}
51
52impl<Output> FunctionMetadata<(), Output> for unsafe fn() -> Output
53where
54    Output: SqlTranslatable,
55{
56    fn entity(&self) -> FunctionMetadataEntity {
57        FunctionMetadataEntity {
58            arguments: vec![],
59            retval: {
60                let marker: PhantomData<Output> = PhantomData;
61                Some(marker.entity())
62            },
63            path: self.path(),
64        }
65    }
66}
67
68impl FunctionMetadata<(), ()> for fn() {
69    fn entity(&self) -> FunctionMetadataEntity {
70        FunctionMetadataEntity { arguments: vec![], retval: None, path: self.path() }
71    }
72}
73
74impl FunctionMetadata<(), ()> for unsafe fn() {
75    fn entity(&self) -> FunctionMetadataEntity {
76        FunctionMetadataEntity { arguments: vec![], retval: None, path: self.path() }
77    }
78}
79seq_macro::seq!(I in 0..=32 {
80    #(
81        seq_macro::seq!(N in 0..=I {
82            impl<#(Input~N,)* Output> FunctionMetadata<(#(Input~N,)*), Output> for fn(#(Input~N,)*) -> Output
83            where
84                #(
85                    Input~N: SqlTranslatable,
86                )*
87                Output: SqlTranslatable,
88            {
89                fn entity(&self) -> FunctionMetadataEntity {
90                    let mut arguments = Vec::new();
91                    #(
92                        arguments.push({
93                            let marker: PhantomData<Input~N> = PhantomData;
94                            marker.entity()
95                        });
96                    )*
97                    FunctionMetadataEntity {
98                        arguments,
99                        retval: {
100                            let marker: PhantomData<Output> = PhantomData;
101                            Some(marker.entity())
102                        },
103                        path: self.path(),
104                    }
105                }
106            }
107
108            impl<#(Input~N,)* Output> FunctionMetadata<(#(Input~N,)*), Output> for unsafe fn(#(Input~N,)*) -> Output
109            where
110                #(
111                    Input~N: SqlTranslatable,
112                )*
113                Output: SqlTranslatable,
114            {
115                fn entity(&self) -> FunctionMetadataEntity {
116                    let mut arguments = Vec::new();
117                    #(
118                        arguments.push({
119                            let marker: PhantomData<Input~N> = PhantomData;
120                            marker.entity()
121                        });
122                    )*
123                    FunctionMetadataEntity {
124                        arguments,
125                        retval: {
126                            let marker: PhantomData<Output> = PhantomData;
127                            Some(marker.entity())
128                        },
129                        path: self.path(),
130                    }
131                }
132            }
133
134            impl<#(Input~N,)*> FunctionMetadata<(#(Input~N,)*), ()> for fn(#(Input~N,)*)
135            where
136                #(
137                    Input~N: SqlTranslatable,
138                )*
139            {
140                fn entity(&self) -> FunctionMetadataEntity {
141                    let mut arguments = Vec::new();
142                    #(
143                        arguments.push({
144                            let marker: PhantomData<Input~N> = PhantomData;
145                            marker.entity()
146                        });
147                    )*
148                    FunctionMetadataEntity {
149                        arguments,
150                        retval: None,
151                        path: self.path(),
152                    }
153                }
154            }
155
156            impl<#(Input~N,)*> FunctionMetadata<(#(Input~N,)*), ()> for unsafe fn(#(Input~N,)*)
157            where
158                #(
159                    Input~N: SqlTranslatable,
160                )*
161            {
162                fn entity(&self) -> FunctionMetadataEntity {
163                    let mut arguments = Vec::new();
164                    #(
165                        arguments.push({
166                            let marker: PhantomData<Input~N> = PhantomData;
167                            marker.entity()
168                        });
169                    )*
170                    FunctionMetadataEntity {
171                        arguments,
172                        retval: None,
173                        path: self.path(),
174                    }
175                }
176            }
177        });
178    )*
179});