-
-
Notifications
You must be signed in to change notification settings - Fork 255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SRF functions need to "fetch" (call FromDatum
) each argument while …
#784
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -440,22 +440,15 @@ impl PgExtern { | |
optional, | ||
} => { | ||
let result_ident = syn::Ident::new("result", self.func.sig.span()); | ||
let funcctx_ident = syn::Ident::new("funcctx", self.func.sig.span()); | ||
let retval_ty_resolved = retval_ty.original_ty; | ||
let result_handler = if optional { | ||
// don't need unsafe annotations because of the larger unsafe block coming up | ||
quote_spanned! { self.func.sig.span() => | ||
let #result_ident = match pgx::PgMemoryContexts::For(funcctx.multi_call_memory_ctx).switch_to(|_| { #func_name(#(#arg_pats),*) }) { | ||
Some(result) => result, | ||
None => { | ||
pgx::srf_return_done(#fcinfo_ident, &mut funcctx); | ||
return pgx::pg_return_null(#fcinfo_ident) | ||
} | ||
}; | ||
#func_name(#(#arg_pats),*) | ||
} | ||
} else { | ||
quote_spanned! { self.func.sig.span() => | ||
let #result_ident = pgx::PgMemoryContexts::For(#funcctx_ident.multi_call_memory_ctx).switch_to(|_| { #func_name(#(#arg_pats),*) }); | ||
Some(#func_name(#(#arg_pats),*)) | ||
} | ||
}; | ||
|
||
|
@@ -478,8 +471,19 @@ impl PgExtern { | |
funcctx.user_fctx = pgx::PgMemoryContexts::For(funcctx.multi_call_memory_ctx).palloc_struct::<IteratorHolder<#retval_ty_resolved>>() as *mut ::core::ffi::c_void; | ||
iterator_holder = pgx::PgBox::from_pg(funcctx.user_fctx as *mut IteratorHolder<#retval_ty_resolved>); | ||
|
||
#( #arg_fetches )* | ||
#result_handler | ||
// function arguments need to be "fetched" while in the function call's | ||
// multi-call-memory-context to ensure that any detoasted datums will | ||
// live long enough for the SRF to use them over each call | ||
Comment on lines
+474
to
+476
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what needs to also be documented in a place outside the context of this function's comments. Especially so because this is something that will always need to remain true: we always must satisfy this sort of lifetime-binding condition, and it doesn't matter whether the code is burned and rewritten a million times: it remains a constraint. It should be easier to reference this sort of information than reading thousands of lines of implementations line by line, because it determines how fast someone can begin to understand the concepts required to write correct code for implementing PGX. |
||
let #result_ident = match pgx::PgMemoryContexts::For(funcctx.multi_call_memory_ctx).switch_to(|_| { | ||
#( #arg_fetches )* | ||
#result_handler | ||
}) { | ||
Some(result) => result, | ||
None => { | ||
pgx::srf_return_done(#fcinfo_ident, &mut funcctx); | ||
return pgx::pg_return_null(#fcinfo_ident) | ||
} | ||
}; | ||
|
||
iterator_holder.iter = pgx::PgMemoryContexts::For(funcctx.multi_call_memory_ctx).leak_trivial_alloc(result); | ||
} | ||
|
@@ -546,17 +550,11 @@ impl PgExtern { | |
let result_handler = if optional { | ||
// don't need unsafe annotations because of the larger unsafe block coming up | ||
quote_spanned! { self.func.sig.span() => | ||
let #result_ident = match pgx::PgMemoryContexts::For(funcctx.multi_call_memory_ctx).switch_to(|_| { #func_name(#(#arg_pats),*) }) { | ||
Some(result) => result, | ||
None => { | ||
pgx::srf_return_done(#fcinfo_ident, &mut funcctx); | ||
return pgx::pg_return_null(#fcinfo_ident) | ||
} | ||
}; | ||
#func_name(#(#arg_pats),*) | ||
} | ||
} else { | ||
quote_spanned! { self.func.sig.span() => | ||
let #result_ident = pgx::PgMemoryContexts::For(#funcctx_ident.multi_call_memory_ctx).switch_to(|_| { #func_name(#(#arg_pats),*) }); | ||
Some(#func_name(#(#arg_pats),*)) | ||
} | ||
}; | ||
|
||
|
@@ -589,8 +587,19 @@ impl PgExtern { | |
}); | ||
iterator_holder = pgx::PgBox::from_pg(funcctx.user_fctx as *mut IteratorHolder<#retval_tys_tuple>); | ||
|
||
#( #arg_fetches )* | ||
#result_handler | ||
// function arguments need to be "fetched" while in the function call's | ||
// multi-call-memory-context to ensure that any detoasted datums will | ||
// live long enough for the SRF to use them over each call | ||
let #result_ident = match pgx::PgMemoryContexts::For(funcctx.multi_call_memory_ctx).switch_to(|_| { | ||
#( #arg_fetches )* | ||
#result_handler | ||
}) { | ||
Some(result) => result, | ||
None => { | ||
pgx::srf_return_done(#fcinfo_ident, &mut funcctx); | ||
return pgx::pg_return_null(#fcinfo_ident) | ||
} | ||
}; | ||
|
||
iterator_holder.iter = pgx::PgMemoryContexts::For(funcctx.multi_call_memory_ctx).leak_and_drop_on_delete(result); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So in this case, the return lifetimes we are expecting will be
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. I think this can be done in a better way in the future, but I can't find the solution immediately and we're staticizing other lifetimes, so I think this is acceptable for the current moment.