drizzle_types/postgres/ddl/
policy.rs1use crate::alloc_prelude::*;
8
9#[cfg(feature = "serde")]
10use crate::serde_helpers::{cow_from_string, cow_option_from_string, cow_option_vec_from_strings};
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
18pub struct PolicyDef {
19 pub schema: &'static str,
21 pub table: &'static str,
23 pub name: &'static str,
25 pub as_clause: Option<&'static str>,
27 pub for_clause: Option<&'static str>,
29 pub to: Option<&'static [&'static str]>,
31 pub using: Option<&'static str>,
33 pub with_check: Option<&'static str>,
35}
36
37impl PolicyDef {
38 #[must_use]
40 pub const fn new(schema: &'static str, table: &'static str, name: &'static str) -> Self {
41 Self {
42 schema,
43 table,
44 name,
45 as_clause: None,
46 for_clause: None,
47 to: None,
48 using: None,
49 with_check: None,
50 }
51 }
52
53 #[must_use]
55 pub const fn as_clause(self, clause: &'static str) -> Self {
56 Self {
57 as_clause: Some(clause),
58 ..self
59 }
60 }
61
62 #[must_use]
64 pub const fn for_clause(self, clause: &'static str) -> Self {
65 Self {
66 for_clause: Some(clause),
67 ..self
68 }
69 }
70
71 #[must_use]
73 pub const fn to(self, roles: &'static [&'static str]) -> Self {
74 Self {
75 to: Some(roles),
76 ..self
77 }
78 }
79
80 #[must_use]
82 pub const fn using(self, expr: &'static str) -> Self {
83 Self {
84 using: Some(expr),
85 ..self
86 }
87 }
88
89 #[must_use]
91 pub const fn with_check(self, expr: &'static str) -> Self {
92 Self {
93 with_check: Some(expr),
94 ..self
95 }
96 }
97
98 #[must_use]
100 pub fn into_policy(self) -> Policy {
101 Policy {
102 schema: Cow::Borrowed(self.schema),
103 table: Cow::Borrowed(self.table),
104 name: Cow::Borrowed(self.name),
105 as_clause: self.as_clause.map(Cow::Borrowed),
106 for_clause: self.for_clause.map(Cow::Borrowed),
107 to: self
108 .to
109 .map(|roles| roles.iter().copied().map(Cow::Borrowed).collect()),
110 using: self.using.map(Cow::Borrowed),
111 with_check: self.with_check.map(Cow::Borrowed),
112 }
113 }
114}
115
116#[derive(Clone, Debug, PartialEq, Eq)]
122#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
123#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
124pub struct Policy {
125 #[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
127 pub schema: Cow<'static, str>,
128
129 #[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
131 pub table: Cow<'static, str>,
132
133 #[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
135 pub name: Cow<'static, str>,
136
137 #[cfg_attr(
139 feature = "serde",
140 serde(
141 rename = "as",
142 skip_serializing_if = "Option::is_none",
143 deserialize_with = "cow_option_from_string"
144 )
145 )]
146 pub as_clause: Option<Cow<'static, str>>,
147
148 #[cfg_attr(
150 feature = "serde",
151 serde(
152 rename = "for",
153 skip_serializing_if = "Option::is_none",
154 deserialize_with = "cow_option_from_string"
155 )
156 )]
157 pub for_clause: Option<Cow<'static, str>>,
158
159 #[cfg_attr(
161 feature = "serde",
162 serde(
163 default,
164 skip_serializing_if = "Option::is_none",
165 deserialize_with = "cow_option_vec_from_strings"
166 )
167 )]
168 pub to: Option<Vec<Cow<'static, str>>>,
169
170 #[cfg_attr(
172 feature = "serde",
173 serde(
174 skip_serializing_if = "Option::is_none",
175 deserialize_with = "cow_option_from_string"
176 )
177 )]
178 pub using: Option<Cow<'static, str>>,
179
180 #[cfg_attr(
182 feature = "serde",
183 serde(
184 skip_serializing_if = "Option::is_none",
185 deserialize_with = "cow_option_from_string"
186 )
187 )]
188 pub with_check: Option<Cow<'static, str>>,
189}
190
191impl Policy {
192 #[must_use]
194 pub fn new(
195 schema: impl Into<Cow<'static, str>>,
196 table: impl Into<Cow<'static, str>>,
197 name: impl Into<Cow<'static, str>>,
198 ) -> Self {
199 Self {
200 schema: schema.into(),
201 table: table.into(),
202 name: name.into(),
203 as_clause: None,
204 for_clause: None,
205 to: None,
206 using: None,
207 with_check: None,
208 }
209 }
210
211 #[inline]
213 #[must_use]
214 pub fn schema(&self) -> &str {
215 &self.schema
216 }
217
218 #[inline]
220 #[must_use]
221 pub fn table(&self) -> &str {
222 &self.table
223 }
224
225 #[inline]
227 #[must_use]
228 pub fn name(&self) -> &str {
229 &self.name
230 }
231}
232
233impl From<PolicyDef> for Policy {
234 fn from(def: PolicyDef) -> Self {
235 def.into_policy()
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242
243 #[test]
244 fn test_const_policy_def() {
245 const POLICY: PolicyDef = PolicyDef::new("public", "users", "users_policy")
246 .for_clause("SELECT")
247 .using("user_id = current_user_id()");
248
249 assert_eq!(POLICY.schema, "public");
250 assert_eq!(POLICY.table, "users");
251 assert_eq!(POLICY.name, "users_policy");
252 }
253
254 #[test]
255 fn test_policy_def_to_policy() {
256 const DEF: PolicyDef = PolicyDef::new("public", "users", "policy");
257 let policy = DEF.into_policy();
258 assert_eq!(policy.schema(), "public");
259 assert_eq!(policy.table(), "users");
260 assert_eq!(policy.name(), "policy");
261 }
262}