pgx_sql_entity_graph/postgres_hash/
mod.rs1pub mod entity;
18
19use crate::enrich::{ToEntityGraphTokens, ToRustCodeTokens};
20use proc_macro2::{Span, TokenStream as TokenStream2};
21use quote::quote;
22use syn::parse::{Parse, ParseStream};
23use syn::{DeriveInput, Ident};
24
25use crate::{CodeEnrichment, ToSqlConfig};
26
27#[derive(Debug, Clone)]
73pub struct PostgresHash {
74 pub name: Ident,
75 pub to_sql_config: ToSqlConfig,
76}
77
78impl PostgresHash {
79 pub fn new(
80 name: Ident,
81 to_sql_config: ToSqlConfig,
82 ) -> Result<CodeEnrichment<Self>, syn::Error> {
83 if !to_sql_config.overrides_default() {
84 crate::ident_is_acceptable_to_postgres(&name)?;
85 }
86 Ok(CodeEnrichment(Self { name, to_sql_config }))
87 }
88
89 pub fn from_derive_input(
90 derive_input: DeriveInput,
91 ) -> Result<CodeEnrichment<Self>, syn::Error> {
92 let to_sql_config =
93 ToSqlConfig::from_attributes(derive_input.attrs.as_slice())?.unwrap_or_default();
94 Self::new(derive_input.ident, to_sql_config)
95 }
96}
97
98impl ToEntityGraphTokens for PostgresHash {
99 fn to_entity_graph_tokens(&self) -> TokenStream2 {
100 let name = &self.name;
101 let sql_graph_entity_fn_name =
102 syn::Ident::new(&format!("__pgx_internals_hash_{}", self.name), Span::call_site());
103 let to_sql_config = &self.to_sql_config;
104 quote! {
105 #[no_mangle]
106 #[doc(hidden)]
107 pub extern "Rust" fn #sql_graph_entity_fn_name() -> ::pgx::pgx_sql_entity_graph::SqlGraphEntity {
108 use core::any::TypeId;
109 extern crate alloc;
110 use alloc::vec::Vec;
111 use alloc::vec;
112 let submission = ::pgx::pgx_sql_entity_graph::PostgresHashEntity {
113 name: stringify!(#name),
114 file: file!(),
115 line: line!(),
116 full_path: core::any::type_name::<#name>(),
117 module_path: module_path!(),
118 id: TypeId::of::<#name>(),
119 to_sql_config: #to_sql_config,
120 };
121 ::pgx::pgx_sql_entity_graph::SqlGraphEntity::Hash(submission)
122 }
123 }
124 }
125}
126
127impl ToRustCodeTokens for PostgresHash {}
128
129impl Parse for CodeEnrichment<PostgresHash> {
130 fn parse(input: ParseStream) -> Result<Self, syn::Error> {
131 use syn::Item;
132
133 let parsed = input.parse()?;
134 let (ident, attrs) = match &parsed {
135 Item::Enum(item) => (item.ident.clone(), item.attrs.as_slice()),
136 Item::Struct(item) => (item.ident.clone(), item.attrs.as_slice()),
137 _ => return Err(syn::Error::new(input.span(), "expected enum or struct")),
138 };
139
140 let to_sql_config = ToSqlConfig::from_attributes(attrs)?.unwrap_or_default();
141 PostgresHash::new(ident, to_sql_config)
142 }
143}