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

Fix issue #1032 #1033

Merged
merged 8 commits into from
Feb 16, 2023
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
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,26 @@ this feature is now considered deprecated in favor of a lower-overhead interop.
You may still request implementations of `TryFrom<time::Type> for pgx::MatchingType`
and `From<time::Type> for pgx::MatchingType` by enabling the `"time-crate"` feature.

### "unsafe-postgres": Allow compilation for Postgres forks that have a different ABI

As of Postgres v15, forks are allowed to specify they use a different ABI than canonical Postgres.
Since pgx makes countless assumptions about Postgres' internal ABI it is not possible for it to
guarantee that a compiled pgx extension will probably execute within such a Postgres fork. You,
dear compiler runner, can make this guarantee for yourself by specifying the `unsafe-postgres`
feature flag. Otherwise, a pgx extension will fail to compile with an error similar to:

```
error[E0080]: evaluation of constant value failed
--> pgx/src/lib.rs:151:5
|
151 | / assert!(
152 | | same_slice(pg_sys::FMGR_ABI_EXTRA, b"xPostgreSQL\0"),
153 | | "Unsupported Postgres ABI. Perhaps you need `--features unsafe-postgres`?",
154 | | );
| |_____^ the evaluated program panicked at 'Unsupported Postgres ABI. Perhaps you need `--features unsafe-postgres`?', pgx/src/lib.rs:151:5
|
```

### Experimental Features

Adding `pgx = { version = "0.5.0", features = ["postgrestd"] }` to your Cargo.toml
Expand Down
1 change: 1 addition & 0 deletions pgx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pg14 = [ "pgx-pg-sys/pg14" ]
pg15 = [ "pgx-pg-sys/pg15" ]
time-crate = ["dep:time"]
no-schema-generation = ["pgx-macros/no-schema-generation", "pgx-sql-entity-graph/no-schema-generation"]
unsafe-postgres = [] # when trying to compile against something that looks like Postgres but claims to be diffent

[package.metadata.docs.rs]
features = ["pg14", "cshim"]
Expand Down
32 changes: 30 additions & 2 deletions pgx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,33 @@ pub use pg_sys::{
#[doc(hidden)]
pub use pgx_sql_entity_graph;

// Postgres v15 has the concept of an ABI "name". The default is `b"PostgreSQL\0"` and this is the
// ABI that pgx extensions expect to be running under. We will refuse to compile if it is detected
// that we're trying to be built against some other kind of "postgres" that has its own ABI name.
//
// Unless the compiling user explicitly told us that they're aware of this via `--features unsafe-postgres`.
#[cfg(all(feature = "pg15", not(feature = "unsafe-postgres")))]
const _: () = {
// to appease `const`
const fn same_slice(a: &[u8], b: &[u8]) -> bool {
if a.len() != b.len() {
return false;
}
let mut i = 0;
while i < a.len() {
if a[i] != b[i] {
return false;
}
i += 1;
}
true
}
assert!(
same_slice(pg_sys::FMGR_ABI_EXTRA, b"PostgreSQL\0"),
"Unsupported Postgres ABI. Perhaps you need `--features unsafe-postgres`?",
);
};

/// A macro for marking a library compatible with [`pgx`][crate].
///
/// <div class="example-wrap" style="display:inline-block">
Expand Down Expand Up @@ -220,8 +247,9 @@ macro_rules! pg_magic_func {
namedatalen: pgx::pg_sys::NAMEDATALEN as i32,
float8byval: cfg!(target_pointer_width = "64") as i32,
abi_extra: {
// array::from_fn isn't const yet, boohoo, so const-copy a bstr
let magic = b"PostgreSQL";
// we'll use what the bindings tell us, but if it ain't "PostgreSQL" then we'll
// raise a compilation error unless the `unsafe-postgres` feature is set
let magic = pgx::pg_sys::FMGR_ABI_EXTRA;
let mut abi = [0 as ::pgx::ffi::c_char; 32];
let mut i = 0;
while i < magic.len() {
Expand Down