1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use crate::sql_entity_graph::pgx_sql::PgxSql;
use crate::sql_entity_graph::to_sql::ToSqlFn;
use crate::sql_entity_graph::SqlGraphEntity;
#[derive(Default, Clone)]
pub struct ToSqlConfigEntity {
pub enabled: bool,
pub callback: Option<ToSqlFn>,
pub content: Option<&'static str>,
}
impl ToSqlConfigEntity {
pub fn to_sql(
&self,
entity: &SqlGraphEntity,
context: &PgxSql,
) -> Option<eyre::Result<String>> {
use eyre::{eyre, WrapErr};
if !self.enabled {
return Some(Ok(format!(
"\n\
{sql_anchor_comment}\n\
-- Skipped due to `#[pgx(sql = false)]`\n",
sql_anchor_comment = entity.sql_anchor_comment(),
)));
}
if let Some(content) = self.content {
let module_pathname = context.get_module_pathname();
let content = content.replace("@MODULE_PATHNAME@", &module_pathname);
return Some(Ok(format!(
"\n\
{sql_anchor_comment}\n\
{content}\n\
",
content = content,
sql_anchor_comment = entity.sql_anchor_comment()
)));
}
if let Some(callback) = self.callback {
let content = callback(entity, context)
.map_err(|e| eyre!(e))
.wrap_err("Failed to run specified `#[pgx(sql = path)] function`");
return match content {
Ok(content) => {
let module_pathname = &context.get_module_pathname();
let content = content.replace("@MODULE_PATHNAME@", &module_pathname);
Some(Ok(format!(
"\n\
{sql_anchor_comment}\n\
{content}\
",
content = content,
sql_anchor_comment = entity.sql_anchor_comment(),
)))
}
Err(e) => Some(Err(e)),
};
}
None
}
}
impl std::cmp::PartialEq for ToSqlConfigEntity {
fn eq(&self, other: &Self) -> bool {
if self.enabled != other.enabled {
return false;
}
match (self.callback, other.callback) {
(None, None) => match (self.content, other.content) {
(None, None) => true,
(Some(a), Some(b)) => a == b,
_ => false,
},
(Some(a), Some(b)) => std::ptr::eq(std::ptr::addr_of!(a), std::ptr::addr_of!(b)),
_ => false,
}
}
}
impl std::cmp::Eq for ToSqlConfigEntity {}
impl std::hash::Hash for ToSqlConfigEntity {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.enabled.hash(state);
self.callback.map(|cb| std::ptr::addr_of!(cb)).hash(state);
self.content.hash(state);
}
}
impl std::fmt::Debug for ToSqlConfigEntity {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let callback = self.callback.map(|cb| std::ptr::addr_of!(cb));
f.debug_struct("ToSqlConfigEntity")
.field("enabled", &self.enabled)
.field("callback", &format_args!("{:?}", &callback))
.field("content", &self.content)
.finish()
}
}