Skip to content
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

Add support for PostgreSQL 12 #86

Merged
merged 1 commit into from
Oct 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pg-extend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ fdw = []
postgres-9 = ["fdw"]
postgres-10 = ["fdw"]
postgres-11 = []
postgres-12 = []
intgr marked this conversation as resolved.
Show resolved Hide resolved

[dependencies]

Expand Down
3 changes: 2 additions & 1 deletion pg-extend/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ fn main() {
.expect("Couldn't write bindings!");

let feature_version = get_postgres_feature_version(pg_include);
println!("cargo:rustc-cfg=feature=\"{}\"", feature_version)
println!("cargo:rustc-cfg=feature=\"{}\"", feature_version);
}

fn include_dir() -> Result<String, env::VarError> {
Expand Down Expand Up @@ -122,6 +122,7 @@ fn get_postgres_feature_version(pg_include: String) -> &'static str {
["9", _] => "postgres-9",
["10"] => "postgres-10",
["11"] => "postgres-11",
["12"] => "postgres-12",
val => panic!("unknown Postgres version {:?}", val),
}
}
47 changes: 35 additions & 12 deletions pg-extend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,43 @@ macro_rules! pg_magic {
};
}

/// Returns the slice of Datums, and a parallel slice which specifies if the Datum passed in is (SQL) NULL
#[cfg(feature = "postgres-12")]
type FunctionCallInfoData = pg_sys::FunctionCallInfoBaseData;
#[cfg(not(feature = "postgres-12"))]
type FunctionCallInfoData = pg_sys::FunctionCallInfoData;

/// Returns an iterator of argument Datums
pub fn get_args<'a>(
func_call_info: &'a pg_sys::FunctionCallInfoData,
) -> (
impl 'a + Iterator<Item = &pg_sys::Datum>,
impl 'a + Iterator<Item = pg_bool::Bool>,
) {
func_call_info: &'a FunctionCallInfoData,
) -> impl 'a + Iterator<Item = Option<pg_sys::Datum>> {
let num_args = func_call_info.nargs as usize;

let args = func_call_info.arg[..num_args].iter();
let args_null = func_call_info.argnull[..num_args]
// PostgreSQL 12+: Convert from pg_sys::NullableDatum
#[cfg(feature = "postgres-12")]
return unsafe { func_call_info.args.as_slice(num_args) }
.iter()
.map(|b| pg_bool::Bool::from(*b));

(args, args_null)
.map(|nullable| {
if nullable.isnull {
None
} else {
Some(nullable.value)
}
});

// Older versions store two separate arrays for 'isnull' and datums
#[cfg(not(feature = "postgres-12"))]
return {
let args = &func_call_info.arg[..num_args];
let args_null = &func_call_info.argnull[..num_args];

args.iter().zip(args_null.iter()).map(|(value, isnull)| {
if pg_bool::Bool::from(*isnull).into() {
None
} else {
Some(*value)
}
})
};
intgr marked this conversation as resolved.
Show resolved Hide resolved
}

/// Information for a longjmp
Expand Down Expand Up @@ -126,7 +148,8 @@ pub fn register_panic_handler() {
pub(crate) unsafe fn guard_pg<R, F: FnOnce() -> R>(f: F) -> R {
// setup the check protection
let original_exception_stack: *mut pg_sys::sigjmp_buf = pg_sys::PG_exception_stack;
let mut local_exception_stack: mem::MaybeUninit<pg_sys::sigjmp_buf> = mem::MaybeUninit::uninit();
let mut local_exception_stack: mem::MaybeUninit<pg_sys::sigjmp_buf> =
mem::MaybeUninit::uninit();
let jumped = pg_sys::sigsetjmp(
// grab a mutable reference, cast to a mutabl pointr, then case to the expected erased pointer type
local_exception_stack.as_mut_ptr() as *mut pg_sys::sigjmp_buf as *mut _,
Expand Down
8 changes: 8 additions & 0 deletions pg-extend/src/pg_datum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ impl<'mc> PgDatum<'mc> {
PgDatum(datum, PhantomData)
}

/// Returns a new PgDatum wrapper if you already have Option<Datum>
pub unsafe fn from_option(
_memory_context: &'mc PgAllocator,
datum: Option<Datum>,
intgr marked this conversation as resolved.
Show resolved Hide resolved
) -> PgDatum<'mc> {
PgDatum(datum, PhantomData)
}

/// Return true if this Datum is None
///
/// # Notes
Expand Down
2 changes: 1 addition & 1 deletion pg-extend/src/pg_fdw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

// FDW on PostgreSQL 11+ is not supported. :(
// If anyone tries to enable "fdw" feature with newer Postgres, throw error.
#[cfg(feature = "postgres-11")]
#[cfg(any(feature = "postgres-11", feature = "postgres-12"))]
compile_error!("pg-extend-rs does not support FDW on PostgreSQL 11 or newer. See https://github.com/bluejekyll/pg-extend-rs/issues/49");

use std::boxed::Box;
Expand Down
19 changes: 8 additions & 11 deletions pg-extern-attr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@
extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;

mod lifetime;
#[macro_use]
extern crate syn;

use proc_macro2::{Ident, Span, TokenStream};
use quote::ToTokens;
Expand All @@ -23,6 +21,8 @@ use syn::spanned::Spanned;
use syn::token::Comma;
use syn::Type;

mod lifetime;

/// A type that represents that PgAllocator is an argument to the Rust function.
type HasPgAllocatorArg = bool;

Expand Down Expand Up @@ -104,14 +104,11 @@ fn extract_arg_data(arg_types: &[Type]) -> (TokenStream, HasPgAllocatorArg) {
let arg_error = format!("unsupported function argument type for {}", arg_name);

let get_arg = quote_spanned!( arg_type.span()=>
let datum = args.next().expect("wrong number of args passed into get_args for args?");
let #arg_name: #arg_type = unsafe {
pg_extend::pg_datum::TryFromPgDatum::try_from(
&memory_context,
pg_extend::pg_datum::PgDatum::from_raw(
&memory_context,
*args.next().expect("wrong number of args passed into get_args for args?"),
args_null.next().expect("wrong number of args passed into get_args for args_null?")
),
pg_extend::pg_datum::PgDatum::from_option(&memory_context, datum),
)
.expect(#arg_error)
};
Expand Down Expand Up @@ -337,7 +334,7 @@ fn impl_info_for_fn(item: &syn::Item) -> TokenStream {
// All params will be in the "current" memory context at the call-site
let memory_context = PgAllocator::current_context();

let func_info: &mut pg_extend::pg_sys::FunctionCallInfoData = unsafe {
let func_info = unsafe {
func_call_info
.as_mut()
.expect("func_call_info was unexpectedly NULL")
Expand All @@ -346,7 +343,7 @@ fn impl_info_for_fn(item: &syn::Item) -> TokenStream {
// guard the Postgres process against the panic, and give us an oportunity to cleanup
let panic_result = panic::catch_unwind(|| {
// extract the argument list
let (mut args, mut args_null) = pg_extend::get_args(func_info);
let mut args = pg_extend::get_args(func_info);

// arbitrary Datum conversions occur here, and could panic
// so this is inside the catch unwind
Expand Down