Skip to content

Commit

Permalink
WIP: Add support for PostgreSQL 12 (except FDW)
Browse files Browse the repository at this point in the history
PostgreSQL 12 brings changes to FunctionCallInfoData (the way arguments
are passed to functions) and the FDW API.

This pull request:
* Implements support for the new call interface (keeping backwards
  compatibility).
* Disables FDW support in PostgreSQL 12.

Upstream commit:
postgres/postgres@a9c35cf
  • Loading branch information
intgr committed Oct 6, 2019
1 parent 3044d63 commit 7b8170a
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 33 deletions.
16 changes: 0 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ members = [
"pg-extend",
"pg-extern-attr",
"examples/adding",
"examples/fdw",
"examples/fdw-rw",
# "examples/fdw",
# "examples/fdw-rw",
"examples/logging",
"examples/memory_context",
"examples/nullable",
Expand Down
2 changes: 2 additions & 0 deletions cookbook
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
rustfmt "$(/bin/ls -1 -t target/*/*/*/out/postgres.rs |head -1)" --emit stdout > pg-extend/src/postgres.rs

1 change: 1 addition & 0 deletions integration-tests/tests/fdw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#![cfg(never)]

extern crate integration_tests;

Expand Down
1 change: 1 addition & 0 deletions pg-extend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ default = ["postgres-10"]
postgres-9 = []
postgres-10 = []
postgres-11 = []
postgres-12 = []

[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 @@ -111,6 +111,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),
}
}
38 changes: 28 additions & 10 deletions pg-extend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,39 @@ 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")]
pub type NullableDatum = pg_sys::NullableDatum;

// PostgreSQL 11 and earlier don't have this type; declare it locally.
#[cfg(not(feature = "postgres-12"))]
pub struct NullableDatum {
pub value: pg_sys::Datum,
pub isnull: bool,
}

/// Returns an iterator of argument Datums and their nullness
#[cfg(feature = "postgres-12")]
pub fn get_args<'a>(
func_call_info: &'a pg_sys::FunctionCallInfoBaseData,
) -> impl 'a + Iterator<Item = &NullableDatum> {
unsafe { func_call_info.args.as_slice(func_call_info.nargs as usize) }.iter()
}

#[cfg(not(feature = "postgres-12"))]
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>,
) {
) -> impl 'a + Iterator<Item = NullableDatum> {
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]
.iter()
.map(|b| pg_bool::Bool::from(*b));
let args = &func_call_info.arg[..num_args];
let args_null = &func_call_info.argnull[..num_args];

(args, args_null)
args.iter()
.zip(args_null.iter())
.map(|(value, isnull)| NullableDatum {
value: *value,
isnull: *isnull,
})
}

/// Information for a longjmp
Expand Down
2 changes: 2 additions & 0 deletions pg-extend/src/pg_fdw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
//! and https://bitbucket.org/adunstan/rotfang-fdw/src/ca21c2a2e5fa6e1424b61bf0170adb3ab4ae68e7/src/rotfang_fdw.c?at=master&fileviewer=file-view-default
//! For use with `#[pg_foreignwrapper]` from pg-extend-attr
// FDW on PostgreSQL 12 is not supported yet :(
#![cfg(not(feature = "postgres-12"))]
use std::boxed::Box;
use std::collections::HashMap;
use std::ffi::{CStr, CString};
Expand Down
10 changes: 6 additions & 4 deletions pg-extern-attr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,15 @@ 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()=>
// Note: datum may be NullableDatum or &NullableDatum depending on Postgres version
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?")
datum.value,
datum.isnull
),
)
.expect(#arg_error)
Expand Down Expand Up @@ -344,7 +346,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 @@ -353,7 +355,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

0 comments on commit 7b8170a

Please sign in to comment.