pgrx_sql_entity_graph/postgres_hash/
mod.rs1pub mod entity;
19
20use crate::enrich::{ToEntityGraphTokens, ToRustCodeTokens};
21use proc_macro2::TokenStream as TokenStream2;
22use quote::{format_ident, quote};
23use syn::parse::{Parse, ParseStream};
24use syn::{DeriveInput, Ident};
25
26use crate::{CodeEnrichment, ToSqlConfig};
27
28#[derive(Debug, Clone)]
74pub struct PostgresHash {
75 pub name: Ident,
76 pub to_sql_config: ToSqlConfig,
77}
78
79impl PostgresHash {
80 pub fn new(
81 name: Ident,
82 to_sql_config: ToSqlConfig,
83 ) -> Result<CodeEnrichment<Self>, syn::Error> {
84 if !to_sql_config.overrides_default() {
85 crate::ident_is_acceptable_to_postgres(&name)?;
86 }
87 Ok(CodeEnrichment(Self { name, to_sql_config }))
88 }
89
90 pub fn from_derive_input(
91 derive_input: DeriveInput,
92 ) -> Result<CodeEnrichment<Self>, syn::Error> {
93 let to_sql_config =
94 ToSqlConfig::from_attributes(derive_input.attrs.as_slice())?.unwrap_or_default();
95 Self::new(derive_input.ident, to_sql_config)
96 }
97}
98
99impl ToEntityGraphTokens for PostgresHash {
100 fn to_entity_graph_tokens(&self) -> TokenStream2 {
101 let name = &self.name;
102 let sql_graph_entity_fn_name = format_ident!("__pgrx_schema_hash_{}", self.name);
103 let to_sql_config = &self.to_sql_config;
104 let to_sql_config_len = to_sql_config.section_len_tokens();
105 let payload_len = quote! {
106 ::pgrx::pgrx_sql_entity_graph::section::u8_len()
107 + ::pgrx::pgrx_sql_entity_graph::section::str_len(stringify!(#name))
108 + ::pgrx::pgrx_sql_entity_graph::section::str_len(file!())
109 + ::pgrx::pgrx_sql_entity_graph::section::u32_len()
110 + ::pgrx::pgrx_sql_entity_graph::section::str_len(stringify!(#name))
111 + ::pgrx::pgrx_sql_entity_graph::section::str_len(module_path!())
112 + ::pgrx::pgrx_sql_entity_graph::section::str_len(<#name as ::pgrx::pgrx_sql_entity_graph::metadata::SqlTranslatable>::TYPE_IDENT)
113 + (#to_sql_config_len)
114 };
115 let total_len = quote! {
116 ::pgrx::pgrx_sql_entity_graph::section::u32_len() + (#payload_len)
117 };
118 let writer = to_sql_config.section_writer_tokens(quote! {
119 ::pgrx::pgrx_sql_entity_graph::section::EntryWriter::<{ #total_len }>::new()
120 .u32((#payload_len) as u32)
121 .u8(::pgrx::pgrx_sql_entity_graph::section::ENTITY_HASH)
122 .str(stringify!(#name))
123 .str(file!())
124 .u32(line!())
125 .str(stringify!(#name))
126 .str(module_path!())
127 .str(<#name as ::pgrx::pgrx_sql_entity_graph::metadata::SqlTranslatable>::TYPE_IDENT)
128 });
129 quote! {
130 ::pgrx::pgrx_sql_entity_graph::__pgrx_schema_entry!(
131 #sql_graph_entity_fn_name,
132 #total_len,
133 #writer.finish()
134 );
135 }
136 }
137}
138
139impl ToRustCodeTokens for PostgresHash {}
140
141impl Parse for CodeEnrichment<PostgresHash> {
142 fn parse(input: ParseStream) -> Result<Self, syn::Error> {
143 use syn::Item;
144
145 let parsed = input.parse()?;
146 let (ident, attrs) = match &parsed {
147 Item::Enum(item) => (item.ident.clone(), item.attrs.as_slice()),
148 Item::Struct(item) => (item.ident.clone(), item.attrs.as_slice()),
149 _ => return Err(syn::Error::new(input.span(), "expected enum or struct")),
150 };
151
152 let to_sql_config = ToSqlConfig::from_attributes(attrs)?.unwrap_or_default();
153 PostgresHash::new(ident, to_sql_config)
154 }
155}