From 11a4d89ace3424ac65ef759648c348c23acc765f Mon Sep 17 00:00:00 2001 From: Sandino Araico Sanchez Date: Tue, 24 Sep 2024 23:23:41 -0600 Subject: [PATCH 1/5] Trait TypmodInOutFuncs for input(input, oid, typmod) function --- pgrx-macros/src/lib.rs | 28 ++++++++++++++++++++++++++++ pgrx/src/inoutfuncs.rs | 20 ++++++++++++++++++++ pgrx/src/prelude.rs | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/pgrx-macros/src/lib.rs b/pgrx-macros/src/lib.rs index b30c2e9791..3fb2433b92 100644 --- a/pgrx-macros/src/lib.rs +++ b/pgrx-macros/src/lib.rs @@ -776,6 +776,7 @@ Optionally accepts the following attributes: PostgresType, attributes( inoutfuncs, + typmod_inoutfuncs, pgvarlena_inoutfuncs, bikeshed_postgres_type_manually_impl_from_into_datum, requires, @@ -963,6 +964,29 @@ fn impl_postgres_type(ast: DeriveInput) -> syn::Result unsafe { buffer.leak_cstr().to_owned() } } }); + } else if args.contains(&PostgresTypeAttribute::TypmodInOutFuncs) { + // otherwise if it's TypmodInOutFuncs our _in/_out functions use an owned type instance + stream.extend(quote! { + #[doc(hidden)] + #[::pgrx::pgrx_macros::pg_extern(immutable,parallel_safe)] + pub fn #funcname_in #generics(input: Option<&::core::ffi::CStr>, oid: Option, typmod: Option) -> Option<#name #generics> { + input.map_or_else(|| { + for m in <#name as ::pgrx::inoutfuncs::TypmodInOutFuncs>::NULL_ERROR_MESSAGE { + ::pgrx::pg_sys::error!("{m}"); + } + None + }, |i| Some(<#name as ::pgrx::inoutfuncs::TypmodInOutFuncs>::input(i, oid, typmod))) + } + + #[doc(hidden)] + #[::pgrx::pgrx_macros::pg_extern(immutable,parallel_safe)] + pub fn #funcname_out #generics(input: #name #generics) -> ::pgrx::ffi::CString { + let mut buffer = ::pgrx::stringinfo::StringInfo::new(); + ::pgrx::inoutfuncs::TypmodInOutFuncs::output(&input, &mut buffer); + // SAFETY: We just constructed this StringInfo ourselves + unsafe { buffer.leak_cstr().to_owned() } + } + }); } else if args.contains(&PostgresTypeAttribute::PgVarlenaInOutFuncs) { // otherwise if it's PgVarlenaInOutFuncs our _in/_out functions use a PgVarlena stream.extend(quote! { @@ -1085,6 +1109,7 @@ fn impl_guc_enum(ast: DeriveInput) -> syn::Result { #[derive(Debug, Hash, Ord, PartialOrd, Eq, PartialEq)] enum PostgresTypeAttribute { InOutFuncs, + TypmodInOutFuncs, PgVarlenaInOutFuncs, Default, ManualFromIntoDatum, @@ -1100,6 +1125,9 @@ fn parse_postgres_type_args(attributes: &[Attribute]) -> HashSet { categorized_attributes.insert(PostgresTypeAttribute::InOutFuncs); } + "typmod_inoutfuncs" => { + categorized_attributes.insert(PostgresTypeAttribute::TypmodInOutFuncs); + } "pgvarlena_inoutfuncs" => { categorized_attributes.insert(PostgresTypeAttribute::PgVarlenaInOutFuncs); } diff --git a/pgrx/src/inoutfuncs.rs b/pgrx/src/inoutfuncs.rs index 5f20d77444..2d23c28cc2 100644 --- a/pgrx/src/inoutfuncs.rs +++ b/pgrx/src/inoutfuncs.rs @@ -17,6 +17,7 @@ use crate::datum::PgVarlena; use crate::*; #[doc(hidden)] pub use serde_json::{from_slice as json_from_slice, to_vec as json_to_vec}; +use crate::pg_sys::Oid; /// `#[derive(Copy, Clone, PostgresType)]` types need to implement this trait to provide the text /// input/output functions for that type @@ -53,3 +54,22 @@ pub trait InOutFuncs { /// error message should be generated? const NULL_ERROR_MESSAGE: Option<&'static str> = None; } + +/// `#[derive(Serialize, Deserialize, PostgresType)]` types may implement this trait if they prefer +/// a textual representation that isn't JSON +/// Input function taking three arguments of types `cstring`, `oid`, `integer`. +pub trait TypmodInOutFuncs { + /// Given a string representation of `Self`, parse it into `Self`. + /// + /// It is expected that malformed input will raise an `error!()` or `panic!()` + fn input(input: &core::ffi::CStr, oid: Option, typmod: Option) -> Self + where + Self: Sized; + + /// Convert `Self` into text by writing to the supplied `StringInfo` buffer + fn output(&self, buffer: &mut StringInfo); + + /// If PostgreSQL calls the conversion function with NULL as an argument, what + /// error message should be generated? + const NULL_ERROR_MESSAGE: Option<&'static str> = None; +} diff --git a/pgrx/src/prelude.rs b/pgrx/src/prelude.rs index 44e2a67878..bb4660d4bb 100644 --- a/pgrx/src/prelude.rs +++ b/pgrx/src/prelude.rs @@ -34,7 +34,7 @@ pub use crate::datum::{ Numeric, PgVarlena, PostgresType, Range, RangeBound, RangeSubType, Time, TimeWithTimeZone, Timestamp, TimestampWithTimeZone, VariadicArray, }; -pub use crate::inoutfuncs::{InOutFuncs, PgVarlenaInOutFuncs}; +pub use crate::inoutfuncs::{InOutFuncs, TypmodInOutFuncs, PgVarlenaInOutFuncs}; // Trigger support pub use crate::trigger_support::{ From 07e483407bfb0e29c06382a49aed6de14df4172c Mon Sep 17 00:00:00 2001 From: Sandino Araico Sanchez Date: Wed, 25 Sep 2024 06:04:55 -0600 Subject: [PATCH 2/5] Segond argument is Oid, not i32 --- pgrx-macros/src/lib.rs | 2 +- pgrx/src/inoutfuncs.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pgrx-macros/src/lib.rs b/pgrx-macros/src/lib.rs index 3fb2433b92..30f5b1027c 100644 --- a/pgrx-macros/src/lib.rs +++ b/pgrx-macros/src/lib.rs @@ -969,7 +969,7 @@ fn impl_postgres_type(ast: DeriveInput) -> syn::Result stream.extend(quote! { #[doc(hidden)] #[::pgrx::pgrx_macros::pg_extern(immutable,parallel_safe)] - pub fn #funcname_in #generics(input: Option<&::core::ffi::CStr>, oid: Option, typmod: Option) -> Option<#name #generics> { + pub fn #funcname_in #generics(input: Option<&::core::ffi::CStr>, oid: pgrx::pg_sys::Oid, typmod: i32) -> Option<#name #generics> { input.map_or_else(|| { for m in <#name as ::pgrx::inoutfuncs::TypmodInOutFuncs>::NULL_ERROR_MESSAGE { ::pgrx::pg_sys::error!("{m}"); diff --git a/pgrx/src/inoutfuncs.rs b/pgrx/src/inoutfuncs.rs index 2d23c28cc2..734dbec036 100644 --- a/pgrx/src/inoutfuncs.rs +++ b/pgrx/src/inoutfuncs.rs @@ -62,7 +62,7 @@ pub trait TypmodInOutFuncs { /// Given a string representation of `Self`, parse it into `Self`. /// /// It is expected that malformed input will raise an `error!()` or `panic!()` - fn input(input: &core::ffi::CStr, oid: Option, typmod: Option) -> Self + fn input(input: &core::ffi::CStr, oid: Oid, typmod: i32) -> Self where Self: Sized; From f7cdaf26440de3e57195ce792da043a3af9a75b8 Mon Sep 17 00:00:00 2001 From: Sandino Araico Sanchez Date: Fri, 27 Sep 2024 05:02:20 -0600 Subject: [PATCH 3/5] typmod_in_fn and typmod_in_fn_module_path in but something is not working... --- pgrx-macros/src/lib.rs | 11 ++++- pgrx-sql-entity-graph/src/lib.rs | 6 ++- .../src/postgres_type/entity.rs | 47 ++++++++++++++++++- .../src/postgres_type/mod.rs | 20 +++++++- pgrx/src/inoutfuncs.rs | 5 ++ 5 files changed, 83 insertions(+), 6 deletions(-) diff --git a/pgrx-macros/src/lib.rs b/pgrx-macros/src/lib.rs index 30f5b1027c..2cabc009c6 100644 --- a/pgrx-macros/src/lib.rs +++ b/pgrx-macros/src/lib.rs @@ -769,6 +769,7 @@ enum Animal { Optionally accepts the following attributes: * `inoutfuncs(some_in_fn, some_out_fn)`: Define custom in/out functions for the type. +* `typmod_inoutfuncs(some_in_fn, some_out_fn, some_typmod_in_fn)`: Define custom in/out functions for the type with typmod. * `pgvarlena_inoutfuncs(some_in_fn, some_out_fn)`: Define custom in/out functions for the `PgVarlena` of this type. * `sql`: Same arguments as [`#[pgrx(sql = ..)]`](macro@pgrx). */ @@ -794,6 +795,7 @@ fn impl_postgres_type(ast: DeriveInput) -> syn::Result let generics = &ast.generics.clone(); let has_lifetimes = generics.lifetimes().next(); let funcname_in = Ident::new(&format!("{name}_in").to_lowercase(), name.span()); + let funcname_typmod_in = Ident::new(&format!("{name}_typmod_in").to_lowercase(), name.span()); let funcname_out = Ident::new(&format!("{name}_out").to_lowercase(), name.span()); let mut args = parse_postgres_type_args(&ast.attrs); let mut stream = proc_macro2::TokenStream::new(); @@ -969,7 +971,7 @@ fn impl_postgres_type(ast: DeriveInput) -> syn::Result stream.extend(quote! { #[doc(hidden)] #[::pgrx::pgrx_macros::pg_extern(immutable,parallel_safe)] - pub fn #funcname_in #generics(input: Option<&::core::ffi::CStr>, oid: pgrx::pg_sys::Oid, typmod: i32) -> Option<#name #generics> { + pub fn #funcname_in #generics(input: Option<&::core::ffi::CStr>, oid: ::pgrx::pg_sys::Oid, typmod: i32) -> Option<#name #generics> { input.map_or_else(|| { for m in <#name as ::pgrx::inoutfuncs::TypmodInOutFuncs>::NULL_ERROR_MESSAGE { ::pgrx::pg_sys::error!("{m}"); @@ -986,6 +988,13 @@ fn impl_postgres_type(ast: DeriveInput) -> syn::Result // SAFETY: We just constructed this StringInfo ourselves unsafe { buffer.leak_cstr().to_owned() } } + + #[doc(hidden)] + #[::pgrx::pgrx_macros::pg_extern(immutable,parallel_safe)] + pub fn #funcname_typmod_in #generics(input: Array<&::core::ffi::CStr>) -> i32 { + <#name as ::pgrx::inoutfuncs::TypmodInOutFuncs>::typmod_in(input) + } + }); } else if args.contains(&PostgresTypeAttribute::PgVarlenaInOutFuncs) { // otherwise if it's PgVarlenaInOutFuncs our _in/_out functions use a PgVarlena diff --git a/pgrx-sql-entity-graph/src/lib.rs b/pgrx-sql-entity-graph/src/lib.rs index 47114eee5e..3e6ff27d5d 100644 --- a/pgrx-sql-entity-graph/src/lib.rs +++ b/pgrx-sql-entity-graph/src/lib.rs @@ -239,6 +239,8 @@ impl ToSql for SqlGraphEntity { in_fn_module_path, out_fn, out_fn_module_path, + typmod_in_fn, + typmod_in_fn_module_path, .. }) = &context.graph[neighbor] else { @@ -249,7 +251,9 @@ impl ToSql for SqlGraphEntity { && item.full_path.ends_with(in_fn); let is_out_fn = item.full_path.starts_with(out_fn_module_path) && item.full_path.ends_with(out_fn); - is_in_fn || is_out_fn + let is_typmod_in_fn = item.full_path.starts_with(typmod_in_fn_module_path) + && item.full_path.ends_with(typmod_in_fn); + is_in_fn || is_out_fn || is_typmod_in_fn }) { Ok(String::default()) diff --git a/pgrx-sql-entity-graph/src/postgres_type/entity.rs b/pgrx-sql-entity-graph/src/postgres_type/entity.rs index 28c6434754..f1fe6849d4 100644 --- a/pgrx-sql-entity-graph/src/postgres_type/entity.rs +++ b/pgrx-sql-entity-graph/src/postgres_type/entity.rs @@ -36,6 +36,8 @@ pub struct PostgresTypeEntity { pub in_fn_module_path: String, pub out_fn: &'static str, pub out_fn_module_path: String, + pub typmod_in_fn: &'static str, + pub typmod_in_fn_module_path: String, pub to_sql_config: ToSqlConfigEntity, } @@ -71,7 +73,9 @@ impl SqlGraphIdentifier for PostgresTypeEntity { impl ToSql for PostgresTypeEntity { fn to_sql(&self, context: &PgrxSql) -> eyre::Result { let self_index = context.types[self]; + //println!("=====> self_index <===== {:?}", self_index); let item_node = &context.graph[self_index]; + //println!("=====> item_node <===== \n{:?}\n==========================", item_node); let SqlGraphEntity::Type(PostgresTypeEntity { name, file, @@ -82,6 +86,8 @@ impl ToSql for PostgresTypeEntity { out_fn, out_fn_module_path, in_fn, + typmod_in_fn, + typmod_in_fn_module_path, .. }) = item_node else { @@ -99,15 +105,18 @@ impl ToSql for PostgresTypeEntity { } else { module_path.to_string() // Presume a local }; + println!("in_fn_module_path: {}",in_fn_module_path); let in_fn_path = format!( "{in_fn_module_path}{maybe_colons}{in_fn}", maybe_colons = if !in_fn_module_path.is_empty() { "::" } else { "" } ); - let (_, _index) = context + println!("in_fn_path: {}", in_fn_path); + let (_, index) = context .externs .iter() .find(|(k, _v)| k.full_path == in_fn_path) .ok_or_else(|| eyre::eyre!("Did not find `in_fn: {}`.", in_fn_path))?; + println!("in_fn_path index: {:?}", index); let (in_fn_graph_index, in_fn_entity) = context .graph .neighbors_undirected(self_index) @@ -118,6 +127,7 @@ impl ToSql for PostgresTypeEntity { _ => None, }) .ok_or_else(|| eyre!("Could not find in_fn graph entity."))?; + //println!("in_fn_graph_index: {:?}\n in_fn_entity: {:?}",in_fn_graph_index,in_fn_entity); let in_fn_sql = in_fn_entity.to_sql(context)?; let out_fn_module_path = if !out_fn_module_path.is_empty() { @@ -146,6 +156,37 @@ impl ToSql for PostgresTypeEntity { .ok_or_else(|| eyre!("Could not find out_fn graph entity."))?; let out_fn_sql = out_fn_entity.to_sql(context)?; + let typmod_in_fn_module_path = if !typmod_in_fn_module_path.is_empty() { + typmod_in_fn_module_path.clone() + } else { + module_path.to_string() // Presume a local + }; + println!("typmod_in_fn_module_path: {}",typmod_in_fn_module_path); + let typmod_in_fn_path = format!( + "{typmod_in_fn_module_path}{maybe_colons}{typmod_in_fn}", + maybe_colons = if !typmod_in_fn_module_path.is_empty() { "::" } else { "" } + ); + println!("typmod_in_fn_path: {}", typmod_in_fn_path); + let (_, index) = context + .externs + .iter() + .find(|(k, _v)| k.full_path == typmod_in_fn_path) + .ok_or_else(|| eyre::eyre!("Did not find `typmod_in_fn: {}`.", typmod_in_fn_path))?; + println!("typmod_in_fn_path index: {:?}", index); + //println!("=====> context.graph <===== \n{:?}\n==========================", context.graph); + let (typmod_in_fn_graph_index, typmod_in_fn_entity) = context + .graph + .neighbors_undirected(self_index) + .find_map(|neighbor| match &context.graph[neighbor] { + SqlGraphEntity::Function(func) if func.full_path == typmod_in_fn_path => { + Some((neighbor, func)) + } + _ => None, + }) + .ok_or_else(|| eyre!("Could not find typmod_in_fn graph entity."))?; + //println!("in_fn_graph_index: {:?}\n in_fn_entity: {:?}",in_fn_graph_index,in_fn_entity); + let typmod_in_fn_sql = typmod_in_fn_entity.to_sql(context)?; + let shell_type = format!( "\n\ -- {file}:{line}\n\ @@ -163,14 +204,16 @@ impl ToSql for PostgresTypeEntity { \tINTERNALLENGTH = variable,\n\ \tINPUT = {schema_prefix_in_fn}{in_fn}, /* {in_fn_path} */\n\ \tOUTPUT = {schema_prefix_out_fn}{out_fn}, /* {out_fn_path} */\n\ + \tTYPMOD_IN = {schema_prefix_typmod_in_fn}{typmod_in_fn}, /* {typmod_in_fn_path} */\n\ \tSTORAGE = extended\n\ );\ ", schema = context.schema_prefix_for(&self_index), schema_prefix_in_fn = context.schema_prefix_for(&in_fn_graph_index), schema_prefix_out_fn = context.schema_prefix_for(&out_fn_graph_index), + schema_prefix_typmod_in_fn = context.schema_prefix_for(&typmod_in_fn_graph_index), }; - Ok(shell_type + "\n" + &in_fn_sql + "\n" + &out_fn_sql + "\n" + &materialized_type) + Ok(shell_type + "\n" + &in_fn_sql + "\n" + &out_fn_sql + "\n" + &typmod_in_fn_sql + "\n" + &materialized_type) } } diff --git a/pgrx-sql-entity-graph/src/postgres_type/mod.rs b/pgrx-sql-entity-graph/src/postgres_type/mod.rs index e563c8f5ec..f9cf9f71eb 100644 --- a/pgrx-sql-entity-graph/src/postgres_type/mod.rs +++ b/pgrx-sql-entity-graph/src/postgres_type/mod.rs @@ -54,6 +54,7 @@ pub struct PostgresTypeDerive { generics: Generics, in_fn: Ident, out_fn: Ident, + typmod_in_fn: Ident, to_sql_config: ToSqlConfig, } @@ -63,12 +64,13 @@ impl PostgresTypeDerive { generics: Generics, in_fn: Ident, out_fn: Ident, + typmod_in_fn: Ident, to_sql_config: ToSqlConfig, ) -> Result, syn::Error> { if !to_sql_config.overrides_default() { crate::ident_is_acceptable_to_postgres(&name)?; } - Ok(CodeEnrichment(Self { generics, name, in_fn, out_fn, to_sql_config })) + Ok(CodeEnrichment(Self { generics, name, in_fn, out_fn, typmod_in_fn, to_sql_config })) } pub fn from_derive_input( @@ -90,11 +92,16 @@ impl PostgresTypeDerive { &format!("{}_out", derive_input.ident).to_lowercase(), derive_input.ident.span(), ); + let funcname_typmod_in = Ident::new( + &format!("{}_typmod_in", derive_input.ident).to_lowercase(), + derive_input.ident.span(), + ); Self::new( derive_input.ident, derive_input.generics, funcname_in, funcname_out, + funcname_typmod_in, to_sql_config, ) } @@ -124,6 +131,7 @@ impl ToEntityGraphTokens for PostgresTypeDerive { let in_fn = &self.in_fn; let out_fn = &self.out_fn; + let typmod_in_fn = &self.typmod_in_fn; let sql_graph_entity_fn_name = format_ident!("__pgrx_internals_type_{}", self.name); @@ -189,6 +197,13 @@ impl ToEntityGraphTokens for PostgresTypeDerive { let _ = path_items.pop(); // Drop the one we don't want. path_items.join("::") }, + typmod_in_fn: stringify!(#typmod_in_fn), + typmod_in_fn_module_path: { + let typmod_in_fn = stringify!(#typmod_in_fn); + let mut path_items: Vec<_> = typmod_in_fn.split("::").collect(); + let _ = path_items.pop(); // Drop the one we don't want. + path_items.join("::") + }, to_sql_config: #to_sql_config, }; ::pgrx::pgrx_sql_entity_graph::SqlGraphEntity::Type(submission) @@ -205,6 +220,7 @@ impl Parse for CodeEnrichment { let to_sql_config = ToSqlConfig::from_attributes(attrs.as_slice())?.unwrap_or_default(); let in_fn = Ident::new(&format!("{}_in", ident).to_lowercase(), ident.span()); let out_fn = Ident::new(&format!("{}_out", ident).to_lowercase(), ident.span()); - PostgresTypeDerive::new(ident, generics, in_fn, out_fn, to_sql_config) + let typmod_in_fn = Ident::new(&format!("{}_in", ident).to_lowercase(), ident.span()); + PostgresTypeDerive::new(ident, generics, in_fn, out_fn, typmod_in_fn, to_sql_config) } } diff --git a/pgrx/src/inoutfuncs.rs b/pgrx/src/inoutfuncs.rs index 734dbec036..c63f8e1e8b 100644 --- a/pgrx/src/inoutfuncs.rs +++ b/pgrx/src/inoutfuncs.rs @@ -18,6 +18,7 @@ use crate::*; #[doc(hidden)] pub use serde_json::{from_slice as json_from_slice, to_vec as json_to_vec}; use crate::pg_sys::Oid; +use core::ffi::CStr; /// `#[derive(Copy, Clone, PostgresType)]` types need to implement this trait to provide the text /// input/output functions for that type @@ -69,6 +70,10 @@ pub trait TypmodInOutFuncs { /// Convert `Self` into text by writing to the supplied `StringInfo` buffer fn output(&self, buffer: &mut StringInfo); + /// The type_modifier_input_function is passed the declared modifier(s) in the form of a cstring array. It must check the values for validity (throwing an error if they are wrong), and if they are correct, return a single non-negative integer value that will be stored as the column “typmod”. + fn typmod_in(input: Array<&CStr>) -> i32 ; + + /// If PostgreSQL calls the conversion function with NULL as an argument, what /// error message should be generated? const NULL_ERROR_MESSAGE: Option<&'static str> = None; From a5831a88004989454181313bc3d9e396f08f66da Mon Sep 17 00:00:00 2001 From: Sandino Araico Sanchez Date: Sun, 6 Oct 2024 06:13:34 -0600 Subject: [PATCH 4/5] Looking for context.graph_root neighbors finds the function but duplicates sql --- .../src/postgres_type/entity.rs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/pgrx-sql-entity-graph/src/postgres_type/entity.rs b/pgrx-sql-entity-graph/src/postgres_type/entity.rs index f1fe6849d4..1564288cd7 100644 --- a/pgrx-sql-entity-graph/src/postgres_type/entity.rs +++ b/pgrx-sql-entity-graph/src/postgres_type/entity.rs @@ -73,9 +73,7 @@ impl SqlGraphIdentifier for PostgresTypeEntity { impl ToSql for PostgresTypeEntity { fn to_sql(&self, context: &PgrxSql) -> eyre::Result { let self_index = context.types[self]; - //println!("=====> self_index <===== {:?}", self_index); let item_node = &context.graph[self_index]; - //println!("=====> item_node <===== \n{:?}\n==========================", item_node); let SqlGraphEntity::Type(PostgresTypeEntity { name, file, @@ -105,18 +103,15 @@ impl ToSql for PostgresTypeEntity { } else { module_path.to_string() // Presume a local }; - println!("in_fn_module_path: {}",in_fn_module_path); let in_fn_path = format!( "{in_fn_module_path}{maybe_colons}{in_fn}", maybe_colons = if !in_fn_module_path.is_empty() { "::" } else { "" } ); - println!("in_fn_path: {}", in_fn_path); - let (_, index) = context + let (_, _index) = context .externs .iter() .find(|(k, _v)| k.full_path == in_fn_path) .ok_or_else(|| eyre::eyre!("Did not find `in_fn: {}`.", in_fn_path))?; - println!("in_fn_path index: {:?}", index); let (in_fn_graph_index, in_fn_entity) = context .graph .neighbors_undirected(self_index) @@ -127,7 +122,6 @@ impl ToSql for PostgresTypeEntity { _ => None, }) .ok_or_else(|| eyre!("Could not find in_fn graph entity."))?; - //println!("in_fn_graph_index: {:?}\n in_fn_entity: {:?}",in_fn_graph_index,in_fn_entity); let in_fn_sql = in_fn_entity.to_sql(context)?; let out_fn_module_path = if !out_fn_module_path.is_empty() { @@ -161,22 +155,18 @@ impl ToSql for PostgresTypeEntity { } else { module_path.to_string() // Presume a local }; - println!("typmod_in_fn_module_path: {}",typmod_in_fn_module_path); let typmod_in_fn_path = format!( "{typmod_in_fn_module_path}{maybe_colons}{typmod_in_fn}", maybe_colons = if !typmod_in_fn_module_path.is_empty() { "::" } else { "" } ); - println!("typmod_in_fn_path: {}", typmod_in_fn_path); - let (_, index) = context + let (_, _index) = context .externs .iter() .find(|(k, _v)| k.full_path == typmod_in_fn_path) .ok_or_else(|| eyre::eyre!("Did not find `typmod_in_fn: {}`.", typmod_in_fn_path))?; - println!("typmod_in_fn_path index: {:?}", index); - //println!("=====> context.graph <===== \n{:?}\n==========================", context.graph); let (typmod_in_fn_graph_index, typmod_in_fn_entity) = context .graph - .neighbors_undirected(self_index) + .neighbors_undirected(context.graph_root) .find_map(|neighbor| match &context.graph[neighbor] { SqlGraphEntity::Function(func) if func.full_path == typmod_in_fn_path => { Some((neighbor, func)) @@ -184,7 +174,6 @@ impl ToSql for PostgresTypeEntity { _ => None, }) .ok_or_else(|| eyre!("Could not find typmod_in_fn graph entity."))?; - //println!("in_fn_graph_index: {:?}\n in_fn_entity: {:?}",in_fn_graph_index,in_fn_entity); let typmod_in_fn_sql = typmod_in_fn_entity.to_sql(context)?; let shell_type = format!( From 9ffc534fbfb64003b8edcc3f1ecb0f167ea925fc Mon Sep 17 00:00:00 2001 From: Sandino Araico Sanchez Date: Mon, 7 Oct 2024 00:40:53 -0600 Subject: [PATCH 5/5] This is what I wanted, but cheating on .neighbors_undirected(context.graph_root) --- pgrx-sql-entity-graph/src/lib.rs | 2 +- pgrx-sql-entity-graph/src/postgres_type/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pgrx-sql-entity-graph/src/lib.rs b/pgrx-sql-entity-graph/src/lib.rs index 3e6ff27d5d..c0d31edd35 100644 --- a/pgrx-sql-entity-graph/src/lib.rs +++ b/pgrx-sql-entity-graph/src/lib.rs @@ -232,7 +232,7 @@ impl ToSql for SqlGraphEntity { result } else if context .graph - .neighbors_undirected(*context.externs.get(item).unwrap()) + .neighbors_undirected(context.graph_root/* *context.externs.get(item).unwrap()*/) .any(|neighbor| { let SqlGraphEntity::Type(PostgresTypeEntity { in_fn, diff --git a/pgrx-sql-entity-graph/src/postgres_type/mod.rs b/pgrx-sql-entity-graph/src/postgres_type/mod.rs index f9cf9f71eb..0351e0a844 100644 --- a/pgrx-sql-entity-graph/src/postgres_type/mod.rs +++ b/pgrx-sql-entity-graph/src/postgres_type/mod.rs @@ -220,7 +220,7 @@ impl Parse for CodeEnrichment { let to_sql_config = ToSqlConfig::from_attributes(attrs.as_slice())?.unwrap_or_default(); let in_fn = Ident::new(&format!("{}_in", ident).to_lowercase(), ident.span()); let out_fn = Ident::new(&format!("{}_out", ident).to_lowercase(), ident.span()); - let typmod_in_fn = Ident::new(&format!("{}_in", ident).to_lowercase(), ident.span()); + let typmod_in_fn = Ident::new(&format!("{}_typmod_in", ident).to_lowercase(), ident.span()); PostgresTypeDerive::new(ident, generics, in_fn, out_fn, typmod_in_fn, to_sql_config) } }