postgres_extension/
fmgr.rs

1
2// postgres includes
3use crate::pg_config::*;
4use crate::postgres::*;
5
6// includes
7use libc::{c_int,c_void};
8use std::marker::PhantomData;
9
10#[macro_export]
11macro_rules! pg_module_magic {
12    () => {
13        #[no_mangle]
14        #[allow(non_snake_case)]
15        pub extern fn Pg_magic_func() -> &'static postgres_extension::fmgr::Pg_magic_struct {
16            &postgres_extension::fmgr::PG_MODULE_MAGIC_DATA
17        }
18    }
19}
20
21// constants
22pub const FUNC_MAX_ARGS: c_int = 100;
23
24// types
25type PGFunction = extern fn(FunctionCallInfo) -> Datum;
26
27#[allow(non_camel_case_types)]
28type fmNodePtr = *mut c_void;
29#[allow(non_camel_case_types)]
30pub type fmAggrefPtr = *mut c_void;
31
32#[repr(C)]
33pub struct Pg_magic_struct {
34    pub len: c_int,
35    pub version: c_int,
36    pub funcmaxargs: c_int,
37    pub indexmaxkeys: c_int,
38    pub nameddatalen: c_int,
39    pub float4byval: c_int,
40    pub float8byval: c_int
41}
42
43#[repr(C)]
44pub struct Pg_finfo_record {
45    pub api_version : c_int,
46}
47
48#[repr(C)]
49pub struct FmgrInfo {
50    fn_addr: PGFunction,
51    fn_oid: c_void,
52    fn_nargs: u16,
53    fn_strict: bool,
54    fn_retset: bool,
55    fn_stats: u8,
56    fn_extra: *mut c_void,
57    fn_mcxt: c_void,
58    fn_expr: fmNodePtr
59}
60
61
62#[repr(C)]
63struct FunctionCallInfoData<'a> {
64    flinfo: *mut FmgrInfo,
65    context: fmNodePtr,
66    result_info: fmNodePtr,
67    fncollation: c_void,
68    isnull: bool,
69    nargs: u16,
70    arg: [Datum; FUNC_MAX_ARGS as usize],
71    argnull: [bool; FUNC_MAX_ARGS as usize],
72    phantom: PhantomData<&'a FmgrInfo>
73}
74
75#[repr(C)]
76pub struct FunctionCallInfo<'a> {
77    ptr: *mut FunctionCallInfoData<'a>,
78    phantom: PhantomData<&'a FunctionCallInfoData<'a>>
79}
80
81// globals
82pub static PG_MODULE_MAGIC_DATA: Pg_magic_struct =
83    Pg_magic_struct {
84        len: std::mem::size_of::<Pg_magic_struct>() as c_int,
85        version: PG_VERSION_NUM / 100,
86        funcmaxargs: FUNC_MAX_ARGS,
87        indexmaxkeys: INDEX_MAX_KEYS,
88        nameddatalen: NAMEDATALEN,
89        float4byval: FLOAT4PASSBYVAL,
90        float8byval: FLOAT8PASSBYVAL
91    };
92
93pub static PG_FUNCTION_INFO_V1_DATA : Pg_finfo_record =
94    Pg_finfo_record { api_version : 1 };
95
96#[macro_export]
97macro_rules! rust_panic_handler {
98    ($e:expr) => {{
99        let result = std::panic::catch_unwind(|| {
100            $e
101        });
102
103        let retval = match result {
104            Ok(val) => val,
105            Err(err_any) => {
106                unsafe {
107                    if err_any.is::<PgError>() {
108                        pg_re_throw();
109                        unreachable!()
110                    }
111
112                    let message =
113                        if let Some(err_str) = err_any.downcast_ref::<&str>() {
114                            format!("{}", err_str)
115                        } else if let Some(err_str) = err_any.downcast_ref::<String>() {
116                            format!("{}", err_str)
117                        } else {
118                            format!("{:?}", err_any)
119                        };
120
121                    elog!(ERROR, "rust panic: {}", message);
122                    unreachable!()
123                }
124            }
125        };
126        return retval
127    }}
128}
129
130// functions
131pub fn pg_getarg(fcinfo: FunctionCallInfo, arg_num: usize) -> Option<Datum> {
132    unsafe {
133        if (*fcinfo.ptr).argnull[arg_num] {
134            assert!( !(*(*fcinfo.ptr).flinfo).fn_strict );
135            None
136        } else {
137            Some((*fcinfo.ptr).arg[arg_num])
138        }
139    }
140}
141