Skip to content

Commit

Permalink
Factor out finfo_tokens (#1673)
Browse files Browse the repository at this point in the history
An initial toehold on refactoring work to partially unify wrapper-fn
expansions in their implementations, especially where it is
correctness-relevant.
  • Loading branch information
workingjubilee authored Apr 23, 2024
1 parent 6fae0dc commit 3ce0391
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 32 deletions.
19 changes: 19 additions & 0 deletions pgrx-sql-entity-graph/src/finfo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use quote::{format_ident, quote};
use syn::{self, ItemFn};

/// Generate the Postgres fn info record
///
/// Equivalent to PG_FUNCTION_INFO_V1, Postgres will sprintf the fn ident, then `dlsym(so, expected_name)`,
/// so it is important to pass exactly the ident that you want to have the record associated with!
pub fn finfo_v1_tokens(ident: proc_macro2::Ident) -> syn::Result<ItemFn> {
let finfo_name = format_ident!("pg_finfo_{ident}");
let tokens = quote! {
#[no_mangle]
#[doc(hidden)]
pub extern "C" fn #finfo_name() -> &'static ::pgrx::pg_sys::Pg_finfo_record {
const V1_API: ::pgrx::pg_sys::Pg_finfo_record = ::pgrx::pg_sys::Pg_finfo_record { api_version: 1 };
&V1_API
}
};
syn::parse2(tokens)
}
1 change: 1 addition & 0 deletions pgrx-sql-entity-graph/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub(crate) mod control_file;
pub(crate) mod enrich;
pub(crate) mod extension_sql;
pub(crate) mod extern_args;
pub(crate) mod finfo;
#[macro_use]
pub(crate) mod fmt;
pub mod lifetimes;
Expand Down
24 changes: 7 additions & 17 deletions pgrx-sql-entity-graph/src/pg_extern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub use cast::PgCast;
pub use operator::PgOperator;
pub use returning::NameMacro;

use crate::finfo::finfo_v1_tokens;
use crate::fmt::ErrHarder;
use crate::ToSqlConfig;
pub(crate) use attribute::Attribute;
Expand Down Expand Up @@ -375,19 +376,7 @@ impl PgExtern {
}
}

fn finfo_tokens(&self) -> TokenStream2 {
let finfo_name = format_ident!("pg_finfo_{}_wrapper", self.func.sig.ident);
quote_spanned! { self.func.sig.span() =>
#[no_mangle]
#[doc(hidden)]
pub extern "C" fn #finfo_name() -> &'static ::pgrx::pg_sys::Pg_finfo_record {
const V1_API: ::pgrx::pg_sys::Pg_finfo_record = ::pgrx::pg_sys::Pg_finfo_record { api_version: 1 };
&V1_API
}
}
}

pub fn wrapper_func(&self) -> TokenStream2 {
pub fn wrapper_func(&self) -> Result<syn::ItemFn, syn::Error> {
let func_name = &self.func.sig.ident;
let func_name_wrapper = format_ident!("{}_wrapper", &self.func.sig.ident);
let func_generics = &self.func.sig.generics;
Expand Down Expand Up @@ -456,15 +445,16 @@ impl PgExtern {
let extern_c_wrapper =
|span, returns_datum: bool, wrapped_contents: proc_macro2::TokenStream| {
let return_ty = returns_datum.then(|| quote! { -> ::pgrx::pg_sys::Datum });
quote_spanned! { span=>
let tokens = quote_spanned! { span=>
#[no_mangle]
#[doc(hidden)]
#unused_lifetimes
#[::pgrx::pgrx_macros::pg_guard]
pub unsafe extern "C" fn #func_name_wrapper #func_generics(#fcinfo_ident: ::pgrx::pg_sys::FunctionCallInfo) #return_ty {
#wrapped_contents
}
}
};
syn::parse2(tokens)
};

match &self.returns {
Expand Down Expand Up @@ -600,8 +590,8 @@ impl ToEntityGraphTokens for PgExtern {
impl ToRustCodeTokens for PgExtern {
fn to_rust_code_tokens(&self) -> TokenStream2 {
let original_func = &self.func;
let wrapper_func = self.wrapper_func();
let finfo_tokens = self.finfo_tokens();
let wrapper_func = self.wrapper_func().unwrap();
let finfo_tokens = finfo_v1_tokens(wrapper_func.sig.ident.clone()).unwrap();

quote_spanned! { self.func.sig.span() =>
#original_func
Expand Down
18 changes: 3 additions & 15 deletions pgrx-sql-entity-graph/src/pg_trigger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub mod attribute;
pub mod entity;

use crate::enrich::{ToEntityGraphTokens, ToRustCodeTokens};
use crate::finfo::finfo_v1_tokens;
use crate::{CodeEnrichment, ToSqlConfig};
use attribute::PgTriggerAttribute;
use proc_macro2::TokenStream as TokenStream2;
Expand Down Expand Up @@ -101,19 +102,6 @@ impl PgTrigger {
};
syn::parse2(tokens)
}

pub fn finfo_tokens(&self) -> Result<ItemFn, syn::Error> {
let finfo_name = format_ident!("pg_finfo_{}_wrapper", self.func.sig.ident);
let tokens = quote! {
#[no_mangle]
#[doc(hidden)]
pub extern "C" fn #finfo_name() -> &'static ::pgrx::pg_sys::Pg_finfo_record {
const V1_API: ::pgrx::pg_sys::Pg_finfo_record = ::pgrx::pg_sys::Pg_finfo_record { api_version: 1 };
&V1_API
}
};
syn::parse2(tokens)
}
}

impl ToEntityGraphTokens for PgTrigger {
Expand Down Expand Up @@ -148,8 +136,8 @@ impl ToEntityGraphTokens for PgTrigger {

impl ToRustCodeTokens for PgTrigger {
fn to_rust_code_tokens(&self) -> TokenStream2 {
let wrapper_func = self.wrapper_tokens().expect("Generating wrappper function for trigger");
let finfo_func = self.finfo_tokens().expect("Generating finfo function for trigger");
let wrapper_func = self.wrapper_tokens().expect("Generating wrapper function for trigger");
let finfo_func = finfo_v1_tokens(wrapper_func.sig.ident.clone()).unwrap();
let func = &self.func;

quote! {
Expand Down

0 comments on commit 3ce0391

Please sign in to comment.