postgres_extension/
fmgr.rs1
2use crate::pg_config::*;
4use crate::postgres::*;
5
6use 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
21pub const FUNC_MAX_ARGS: c_int = 100;
23
24type 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
81pub 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
130pub 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