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

Generate bindings for functions provided by the cshim using bindgen. #818

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion cargo-pgx/src/command/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub(crate) struct Connect {
#[clap(env = "DBNAME")]
dbname: Option<String>,
#[clap(from_global, action = ArgAction::Count)]
verbose: usize,
verbose: u8,
/// Package to determine default `pg_version` with (see `cargo help pkgid`)
#[clap(long, short)]
package: Option<String>,
Expand Down
51 changes: 28 additions & 23 deletions pgx-pg-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,14 @@ fn generate_bindings(
is_for_release: bool,
) -> eyre::Result<()> {
let major_version = pg_config.major_version().wrap_err("could not determine major version")?;
let mut include_h = build_paths.manifest_dir.clone();
include_h.push("include");
include_h.push(format!("pg{}.h", major_version));

let bindgen_output = run_bindgen(&pg_config, &include_h)
let header_src = format!(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cute.

I wonder if our c-shim should be last? It probably doesn't matter, but I guess bindgen would start by picking up its #includes first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if our c-shim should be last?

I did it first in order to catch any cases where it is using files without including them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admittedly we'd probably catch that when building the cshim, so I don't mind putting it second really.

r#"
#include "cshim/pgx-cshim.h"
#include "include/pg{major_version}.h"
"#
);

let bindgen_output = run_bindgen(&pg_config, &build_paths.manifest_dir, &header_src)
.wrap_err_with(|| format!("bindgen failed for pg{}", major_version))?;

let oids = extract_oids(&bindgen_output);
Expand Down Expand Up @@ -543,13 +546,18 @@ struct StructDescriptor<'a> {

/// Given a specific postgres version, `run_bindgen` generates bindings for the given
/// postgres version and returns them as a token stream.
fn run_bindgen(pg_config: &PgConfig, include_h: &PathBuf) -> eyre::Result<syn::File> {
fn run_bindgen(
pg_config: &PgConfig,
manifest_path: &PathBuf,
header_src: &str,
) -> eyre::Result<syn::File> {
let major_version = pg_config.major_version()?;
eprintln!("Generating bindings for pg{}", major_version);
let includedir_server = pg_config.includedir_server()?;
let bindings = bindgen::Builder::default()
.header(include_h.display().to_string())
.header_contents("combined-header.h", header_src)
.clang_arg(&format!("-I{}", includedir_server.display()))
.clang_arg(&format!("-I{}", manifest_path.display()))
.clang_args(&extra_bindgen_clang_args(pg_config)?)
.parse_callbacks(Box::new(PgxOverrides::default()))
.blocklist_type("(Nullable)?Datum") // manually wrapping datum types for correctness
Expand Down Expand Up @@ -624,23 +632,20 @@ fn build_shim_for_version(
eprintln!("shim_dst={}", shim_dst.display());

std::fs::create_dir_all(shim_dst).unwrap();

if !std::path::Path::new(&format!("{}/Makefile", shim_dst.display())).exists() {
std::fs::copy(
format!("{}/Makefile", shim_src.display()),
format!("{}/Makefile", shim_dst.display()),
)
.unwrap();
}

if !std::path::Path::new(&format!("{}/pgx-cshim.c", shim_dst.display())).exists() {
std::fs::copy(
format!("{}/pgx-cshim.c", shim_src.display()),
format!("{}/pgx-cshim.c", shim_dst.display()),
)
.unwrap();
for entry in std::fs::read_dir(shim_src)? {
let entry = entry?;
let dest_file = shim_dst.join(entry.file_name());
if !dest_file.exists() {
std::fs::copy(entry.path(), &dest_file).unwrap_or_else(|e| {
panic!(
"Failed to copy shim file from {:?} to {:?}: {:?}",
entry.path(),
dest_file,
e,
);
});
}
}

let make = option_env!("MAKE").unwrap_or("make").to_string();
let rc = run_command(
Command::new(make)
Expand Down
60 changes: 6 additions & 54 deletions pgx-pg-sys/cshim/pgx-cshim.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,159 +6,111 @@ All rights reserved.

Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/
#include "postgres.h"
#include "pgx-cshim.h"

#define IS_PG_10 (PG_VERSION_NUM >= 100000 && PG_VERSION_NUM < 110000)
#define IS_PG_11 (PG_VERSION_NUM >= 110000 && PG_VERSION_NUM < 120000)
#define IS_PG_12 (PG_VERSION_NUM >= 120000 && PG_VERSION_NUM < 130000)
#define IS_PG_13 (PG_VERSION_NUM >= 130000 && PG_VERSION_NUM < 140000)

#include "access/htup.h"
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#if IS_PG_10 || IS_PG_11
#include "nodes/relation.h"
#else
#include "nodes/pathnodes.h"
#endif
#include "nodes/pg_list.h"
#include "parser/parsetree.h"
#include "utils/memutils.h"
#include "utils/builtins.h"
#include "utils/array.h"
#include "storage/spin.h"


PGDLLEXPORT MemoryContext pgx_GetMemoryContextChunk(void *ptr);
MemoryContext pgx_GetMemoryContextChunk(void *ptr) {
return GetMemoryChunkContext(ptr);
}

PGDLLEXPORT void pgx_elog(int32 level, char *message);
void pgx_elog(int32 level, char *message) {
void pgx_elog(int32 level, const char *message) {
elog(level, "%s", message);
}

PGDLLEXPORT void pgx_elog_error(char *message);
void pgx_elog_error(char *message) {
void pgx_elog_error(const char *message) {
elog(ERROR, "%s", message);
}

PGDLLEXPORT void pgx_ereport(int level, int code, char *message, char *file, int lineno, int colno);
void pgx_ereport(int level, int code, char *message, char *file, int lineno, int colno) {
void pgx_ereport(int level, int code, const char *message, const char *file, int lineno, int colno) {
ereport(level,
(errcode(code),
errmsg("%s", message), errcontext_msg("%s:%d:%d", file, lineno, colno)));
}

PGDLLEXPORT void pgx_SET_VARSIZE(struct varlena *ptr, int size);
void pgx_SET_VARSIZE(struct varlena *ptr, int size) {
SET_VARSIZE(ptr, size);
}

PGDLLEXPORT void pgx_SET_VARSIZE_SHORT(struct varlena *ptr, int size);
void pgx_SET_VARSIZE_SHORT(struct varlena *ptr, int size) {
SET_VARSIZE_SHORT(ptr, size);
}

PGDLLEXPORT Datum pgx_heap_getattr(HeapTupleData *tuple, int attnum, TupleDesc tupdesc, bool *isnull);
Datum pgx_heap_getattr(HeapTupleData *tuple, int attnum, TupleDesc tupdesc, bool *isnull) {
return heap_getattr(tuple, attnum, tupdesc, isnull);
}

PGDLLEXPORT TransactionId pgx_HeapTupleHeaderGetXmin(HeapTupleHeader htup_header);
TransactionId pgx_HeapTupleHeaderGetXmin(HeapTupleHeader htup_header) {
return HeapTupleHeaderGetXmin(htup_header);
}

PGDLLEXPORT CommandId pgx_HeapTupleHeaderGetRawCommandId(HeapTupleHeader htup_header);
CommandId pgx_HeapTupleHeaderGetRawCommandId(HeapTupleHeader htup_header) {
return HeapTupleHeaderGetRawCommandId(htup_header);
}

PGDLLEXPORT RangeTblEntry *pgx_planner_rt_fetch(Index index, PlannerInfo *plannerInfo);
RangeTblEntry *pgx_planner_rt_fetch(Index index, PlannerInfo *root) {
return planner_rt_fetch(index, root);
}

PGDLLEXPORT void *pgx_list_nth(List *list, int nth);
void *pgx_list_nth(List *list, int nth) {
return list_nth(list, nth);
}

PGDLLEXPORT int pgx_list_nth_int(List *list, int nth);
int pgx_list_nth_int(List *list, int nth) {
return list_nth_int(list, nth);
}

PGDLLEXPORT Oid pgx_list_nth_oid(List *list, int nth);
Oid pgx_list_nth_oid(List *list, int nth) {
return list_nth_oid(list, nth);
}

PGDLLEXPORT ListCell *pgx_list_nth_cell(List *list, int nth);
ListCell *pgx_list_nth_cell(List *list, int nth) {
return list_nth_cell(list, nth);
}

#if IS_PG_10 || IS_PG_11
PGDLLEXPORT Oid pgx_HeapTupleHeaderGetOid(HeapTupleHeader htup_header);
Oid pgx_HeapTupleHeaderGetOid(HeapTupleHeader htup_header) {
return HeapTupleHeaderGetOid(htup_header);
}
#endif

PGDLLEXPORT char *pgx_GETSTRUCT(HeapTuple tuple);
char *pgx_GETSTRUCT(HeapTuple tuple) {
return GETSTRUCT(tuple);
}

PGDLLEXPORT char *pgx_ARR_DATA_PTR(ArrayType *arr);
char *pgx_ARR_DATA_PTR(ArrayType *arr) {
return ARR_DATA_PTR(arr);
}

PGDLLEXPORT int pgx_ARR_NELEMS(ArrayType *arr);
int pgx_ARR_NELEMS(ArrayType *arr) {
return ArrayGetNItems(arr->ndim, ARR_DIMS(arr));
}

PGDLLEXPORT bits8 *pgx_ARR_NULLBITMAP(ArrayType *arr);
bits8 *pgx_ARR_NULLBITMAP(ArrayType *arr) {
return ARR_NULLBITMAP(arr);
}

PGDLLEXPORT int pgx_ARR_NDIM(ArrayType *arr);
int pgx_ARR_NDIM(ArrayType *arr) {
return ARR_NDIM(arr);
}

PGDLLEXPORT bool pgx_ARR_HASNULL(ArrayType *arr);
bool pgx_ARR_HASNULL(ArrayType *arr) {
_Bool pgx_ARR_HASNULL(ArrayType *arr) {
return ARR_HASNULL(arr);
}

PGDLLEXPORT int *pgx_ARR_DIMS(ArrayType *arr);
int *pgx_ARR_DIMS(ArrayType *arr){
return ARR_DIMS(arr);
}

PGDLLEXPORT void pgx_SpinLockInit(volatile slock_t *lock);
void pgx_SpinLockInit(volatile slock_t *lock) {
SpinLockInit(lock);
}

PGDLLEXPORT void pgx_SpinLockAcquire(volatile slock_t *lock);
void pgx_SpinLockAcquire(volatile slock_t *lock) {
SpinLockAcquire(lock);
}

PGDLLEXPORT void pgx_SpinLockRelease(volatile slock_t *lock);
void pgx_SpinLockRelease(volatile slock_t *lock) {
SpinLockRelease(lock);
}

PGDLLEXPORT bool pgx_SpinLockFree(slock_t *lock);
bool pgx_SpinLockFree(slock_t *lock) {
_Bool pgx_SpinLockFree(slock_t *lock) {
return SpinLockFree(lock);
}
61 changes: 61 additions & 0 deletions pgx-pg-sys/cshim/pgx-cshim.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
Portions Copyright 2019-2021 ZomboDB, LLC.
Portions Copyright 2021-2022 Technology Concepts & Design, Inc. <[email protected]>

All rights reserved.

Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/
#pragma once
#include "postgres.h"

#define IS_PG_10 (PG_VERSION_NUM >= 100000 && PG_VERSION_NUM < 110000)
#define IS_PG_11 (PG_VERSION_NUM >= 110000 && PG_VERSION_NUM < 120000)
#define IS_PG_12 (PG_VERSION_NUM >= 120000 && PG_VERSION_NUM < 130000)
#define IS_PG_13 (PG_VERSION_NUM >= 130000 && PG_VERSION_NUM < 140000)

#include "access/htup.h"
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#if IS_PG_10 || IS_PG_11
#include "nodes/relation.h"
#else
#include "nodes/pathnodes.h"
#endif
#include "nodes/pg_list.h"
#include "parser/parsetree.h"
#include "utils/memutils.h"
#include "utils/builtins.h"
#include "utils/array.h"
#include "storage/spin.h"

PGDLLEXPORT MemoryContext pgx_GetMemoryContextChunk(void *ptr);
PGDLLEXPORT void pgx_elog(int32 level, const char *message);
PGDLLEXPORT void pgx_elog_error(const char *message);
PGDLLEXPORT void pgx_ereport(int level, int code, const char *message, const char *file, int lineno, int colno);
PGDLLEXPORT void pgx_SET_VARSIZE(struct varlena *ptr, int size);
PGDLLEXPORT void pgx_SET_VARSIZE_SHORT(struct varlena *ptr, int size);
PGDLLEXPORT Datum pgx_heap_getattr(HeapTupleData *tuple, int attnum, TupleDesc tupdesc, bool *isnull);
PGDLLEXPORT TransactionId pgx_HeapTupleHeaderGetXmin(HeapTupleHeader htup_header);
PGDLLEXPORT CommandId pgx_HeapTupleHeaderGetRawCommandId(HeapTupleHeader htup_header);
PGDLLEXPORT RangeTblEntry *pgx_planner_rt_fetch(Index index, PlannerInfo *plannerInfo);
PGDLLEXPORT void *pgx_list_nth(List *list, int nth);
PGDLLEXPORT int pgx_list_nth_int(List *list, int nth);
PGDLLEXPORT Oid pgx_list_nth_oid(List *list, int nth);
PGDLLEXPORT ListCell *pgx_list_nth_cell(List *list, int nth);
#if IS_PG_10 || IS_PG_11
PGDLLEXPORT Oid pgx_HeapTupleHeaderGetOid(HeapTupleHeader htup_header);
#endif
PGDLLEXPORT char *pgx_GETSTRUCT(HeapTuple tuple);
PGDLLEXPORT char *pgx_ARR_DATA_PTR(ArrayType *arr);
PGDLLEXPORT int pgx_ARR_NELEMS(ArrayType *arr);
PGDLLEXPORT bits8 *pgx_ARR_NULLBITMAP(ArrayType *arr);
PGDLLEXPORT int pgx_ARR_NDIM(ArrayType *arr);
PGDLLEXPORT int *pgx_ARR_DIMS(ArrayType *arr);
PGDLLEXPORT void pgx_SpinLockInit(volatile slock_t *lock);
PGDLLEXPORT void pgx_SpinLockAcquire(volatile slock_t *lock);
PGDLLEXPORT void pgx_SpinLockRelease(volatile slock_t *lock);
// Use `_Bool` and not `bool` until we can drop PG10, since under that version
// `bool` will be an 8 bit integer, which impacts bindgen output.
PGDLLEXPORT _Bool pgx_ARR_HASNULL(ArrayType *arr);
PGDLLEXPORT _Bool pgx_SpinLockFree(slock_t *lock);
53 changes: 6 additions & 47 deletions pgx-pg-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,6 @@ impl AsPgCStr for String {
/// item declarations we want to add to all versions
mod all_versions {
use crate as pg_sys;
use pgx_macros::*;

use memoffset::*;
use std::str::FromStr;

Expand All @@ -243,15 +241,6 @@ mod all_versions {
pub const FirstNormalTransactionId: super::TransactionId = 3 as super::TransactionId;
pub const MaxTransactionId: super::TransactionId = 0xFFFF_FFFF as super::TransactionId;

#[pgx_macros::pg_guard]
extern "C" {
pub fn pgx_list_nth(list: *mut super::List, nth: i32) -> *mut std::os::raw::c_void;
pub fn pgx_list_nth_int(list: *mut super::List, nth: i32) -> i32;
pub fn pgx_list_nth_oid(list: *mut super::List, nth: i32) -> super::Oid;
pub fn pgx_list_nth_cell(list: *mut super::List, nth: i32) -> *mut super::ListCell;
pub fn pgx_GETSTRUCT(tuple: pg_sys::HeapTuple) -> *mut std::os::raw::c_char;
}

#[inline]
pub fn VARHDRSZ_EXTERNAL() -> usize {
offset_of!(super::varattrib_1b_e, va_data)
Expand Down Expand Up @@ -322,7 +311,7 @@ mod all_versions {
index: super::Index,
range_table: *mut super::List,
) -> *mut super::RangeTblEntry {
pgx_list_nth(range_table, index as i32 - 1) as *mut super::RangeTblEntry
pg_sys::pgx_list_nth(range_table, index as i32 - 1) as *mut super::RangeTblEntry
}

#[inline]
Expand Down Expand Up @@ -429,44 +418,14 @@ mod all_versions {
if htup.is_null() {
0 as *mut T
} else {
unsafe { pgx_GETSTRUCT(htup) as *mut T }
unsafe { pg_sys::pgx_GETSTRUCT(htup) as *mut T }
}
}

#[pg_guard]
extern "C" {
pub fn query_tree_walker(
query: *mut super::Query,
walker: ::std::option::Option<
unsafe extern "C" fn(*mut super::Node, *mut ::std::os::raw::c_void) -> bool,
>,
context: *mut ::std::os::raw::c_void,
flags: ::std::os::raw::c_int,
) -> bool;
}

#[pg_guard]
extern "C" {
pub fn expression_tree_walker(
node: *mut super::Node,
walker: ::std::option::Option<
unsafe extern "C" fn(*mut super::Node, *mut ::std::os::raw::c_void) -> bool,
>,
context: *mut ::std::os::raw::c_void,
) -> bool;
}

#[pgx_macros::pg_guard]
extern "C" {
#[link_name = "pgx_SpinLockInit"]
pub fn SpinLockInit(lock: *mut pg_sys::slock_t);
#[link_name = "pgx_SpinLockAcquire"]
pub fn SpinLockAcquire(lock: *mut pg_sys::slock_t);
#[link_name = "pgx_SpinLockRelease"]
pub fn SpinLockRelease(lock: *mut pg_sys::slock_t);
#[link_name = "pgx_SpinLockFree"]
pub fn SpinLockFree(lock: *mut pg_sys::slock_t) -> bool;
}
pub use crate::{
pgx_SpinLockAcquire as SpinLockAcquire, pgx_SpinLockFree as SpinLockFree,
pgx_SpinLockInit as SpinLockInit, pgx_SpinLockRelease as SpinLockRelease,
};
}

mod internal {
Expand Down
Loading