Releases: pgcentralfoundation/pgrx
v0.6.0-alpha.0
Welcome to the first prerelease of pgx 0.6.0!
Remember to use cargo install cargo-pgx --version 0.6.0-alpha.0 --locked
!
Postgres Major Support
This release introduces support for Postgres 15 and drops support for Postgres 10, thanks to @Smittyvb, @BradyBonnette, @yrashk, and @steve-chavez.
Numeric
Thanks to @eeeebbbbrrrr, proper support for SQL's NUMERIC has landed in PGX, using two types:
AnyNumeric
Numeric<const P: u32, const S: u32>
Obviously, this breaks code using Numeric
as it currently is, which is more like AnyNumeric
.
Usage Note: As far as we are able to discern, AnyNumeric
is the type used by Postgres on SQL function entry and exit, even if you specify a precision and scale in SQL, so for the case of #[pg_extern]
you should probably prefer AnyNumeric
, and deliberately convert to Numeric<P, S>
inside functions if needed. Numeric<P,S>
helps most with serialization, writing to tables, and other cases Postgres also uses strict precision and scale.
Error Handling has been revamped
Error handling has been revamped in a way that may be breaking if you were directly handling PGX's error-handling functions, which are intended to be used when you extend this with your own error-handling abstractions. This includes a lot more support for the kinds of patterns allowed by PG_TRY
and PG_CATCH
. Take a look at PgTryBuilder
.
cargo pgx can use rustls
!
You can now configure cargo-pgx
to use rustls
instead of native SSL, but you must intentionally build it that way for now.
Data can now actually return!
@yrashk expanded the ability of various contexts to allow data to escape them: background workers can return values from transaction
, and Spi::connect
can now return values without the FromDatum + IntoDatum
bound.
Performance with soundness?
- It's now almost reasonable to use PGX with multithreading, as @thomcc gave us a true check for calling FFI from multiple threads that is more resilient to being fooled by renaming threads or other oddness you might get up to.
Array::over
is no more 🎉 andArray
is now slightly faster thanks to @workingjubilee. More changes will bring further improvements.- @eeeebbbbrrrr made
direct_function_call
have less overhead
pgx-pg-sys
build improvements
Pertinent to our Postgres version support updates, @BradyBonnette taught pgx-pg-sys
how to warn if you use an unsupported version of Postgres. @thomcc also removed our need for rayon
to build. We also gained some bindings:
- Include extension & namespace catalogs by @yrashk in #836
- Add bindings for typedefs within replication/logical.h to pg_sys by @agamble in #827
Miscellaneous Improvements
Most other changes are more subtle quality of life improvements:
- There are now safe wrappers for
SpinLock
thanks to @thomcc SpiHeapTupleDataEntry
gains an::oid
getter thanks to @workingjubileecore::ffi::CStr
is now available in Rust, and now PGX uses it consistently throughout API thanks to @thomccSpiTupleTable
exposes some getters for information oncolumns
, etc. thanks to @yrashk- We can now handle your esoteric patched Postgres version string thanks to @jteplitz
- PGX will now configure databases to use C.UTF-8 locale when it creates them thanks to @Smittyvb
- Thanks to @thomcc
#[pg_guard]
should now preserve attributes - We now have
{run,explain}_with_args
thanks to @montanalow - We now test multiple distros thanks to @BradyBonnette!
- The
indicies
function now isindices
thanks to @jteplitz - @jteplitz added support for a new PgHook
post_parse_analyze
- PostgresType now supports Rust enums as well thanks to @yrashk
New Contributors
- @jteplitz made their first contribution in #788
- @montanalow made their first contribution in #689
- @felipe-vaultree made their first contribution in #842
- @agamble made their first contribution in #827
Full Changelog: v0.5.6...v0.6.0-alpha.0
v0.5.6
This is pgx v0.5.6. It is a small bugfix release that includes the fix from PR #807.
Please cargo install --locked cargo-pgx
and update your Cargo.toml:
pgx = "0.5.6"
Fixed Bugs
- Functions using the
name!()
macro in their return type (returning aTableIterator
or(rust, tuple)
) can now use Rust reserved keywords as the first "column name" argument. This was a regression introduced in 0.5.3.
Full Changelog: v0.5.4...v0.5.6
v0.5.4
pgx v0.5.4 is out, please cargo install --locked cargo-pgx
and update your Cargo.toml:
pgx = "0.5.4"
This is a fairly small release, containing a bugfix and some new API surface:
- An incorrect handling of some Datum arguments fixed thanks to @eeeebbbbrrrr in #795
- Some missed SpinLock macro bindings were added thanks to @thomcc in #793
- A new base API for dynamic background worker registration was introduced thanks to @yrashk in #710!
We're excited to see further improvements to the Dynamic Background Worker API and are looking forward to any feedback you have!
Full Changelog: v0.5.3...v0.5.4
v0.5.3
What was presumed to be a no-op change after testing on multiple operating systems nonetheless broke the build on Red Hat distros. We're looking into adding another distro (presumably one that is fond of fedoras?) in our CI just to prevent this from happening again and allow us to better anticipate repackages of Postgres with a nonzero number of quirks. This release primarily is to fix that by removing allowlist_*
from our bindgen invocation for now, thanks to @BradyBonnette in #760.
It also fixes a use-after-free that PGX was inducing in Postgres: Datum arguments were being unboxed (into... new boxes, usually) during set-returning functions, but not using the multi-call memory context. This was fixed thanks to @eeeebbbbrrrr in #784
However, it does have a number of other changes.
Less unnecessary dynamic linkage
Some of the dynamic linkage PGX was asking for was largely unnecessary. In new PGX projects, you should now be able to use exotic linkers which don't accept various command line arguments other linkers do... on Linux, as the dynamic lookup argument remains necessary on MacOS (for now), thanks to "Only specify -undefined dynamic_lookup
on macOS" by @thomcc in #754
To get this benefit in an existing project, replace the existing [build]
key in your ./.cargo/config{,.toml}
with
[target.'cfg(target_os="macos")']
# Postgres symbols won't be available until runtime
rustflags = ["-Clink-arg=-Wl,-undefined,dynamic_lookup"]
cargo-pgx improvements
cargo pgx init
now accepts the flags --base-port
and --base-testing-port
, thanks to "Problem: working with independent extensions simultaneously" by @yrashk in #765. These values can be later changed in $PGX_HOME/config.toml
. This is intended to make it easier to work with multiple extensions at once.
We now support --profile <profile name>
in cargo-pgx
thanks to @thomcc in #758, to allow you to better tune the testing and packaging profiles you may want to use.
New pg_sys
bindings
- Enable low-level access to the database catalog by @yrashk in #709
- Added includes for "storage/spin.h" by @osawyerr in #775
Other minor fixups
- We've stopped distorting the signatures of variadic functions thanks to @thomcc in #757
- The
--bgworker
template was found to have fallen out of sync and was patched by @workingjubilee in #768 - Remove lifetimes from FunctionMetadata impl by @thomcc in #772
- derive Debug for PgLogLevel and PgSqlErrorCode by @yrashk in #786
- Make syntect an optional dependency, only used by cargo-pgx by @thomcc in #755
- Avoid some dependencies in pgx-pg-sys by @thomcc in #756
New Contributors
Full Changelog: v0.5.2...v0.5.3
v0.5.2
This is pgx v0.5.2. It is a very minor release that fixes issue #762.
Full Changelog: v0.5.0...v0.5.2
v0.5.0
This is the release of pgx 0.5.0! Special thanks to @BradyBonnette, @JamesGuthrie, @Smittyvb, and @willmurnane for contributing fixes for bugs that we noticed in the last round of testing for 0.5.0-beta.1. Most of these release notes will be a reprise of those if you have seen them already. For everyone else, welcome aboard!
With a rustup
or cargo
toolchain installed, you can download pgx from crates.io, just cargo install --locked cargo-pgx --version 0.5.0
and add this to your Cargo.toml:
pgx = "0.5.0"
API documentation is available on docs.rs.
For newer users
Code written using pgx can now use pgx::prelude::*;
instead of use pgx::*;
and in many cases this will make the extension compile with only a few additional explicit imports. Existing extensions may require extra effort and may want to approach this more incrementally.
Upgrading
Most of the transition should be smooth, except for certain extensions. You will need to reinstall cargo pgx
first: everything regarding SQL generation changed internally, and cargo pgx is the binary that handles most of the actual SQL compilation. We now recommend using cargo install --locked cargo-pgx --version 0.5.0
for this.
There are four major pain points you may immediately encounter: code that directly handles datums, using FromDatum
, date/time types, and set-returning or table-returning functions. But after that compiles, you will also want to address any soundness or behavior questions that might arise regarding Arrays in your code.
Handling Datums
Since 0.5.0-beta.0
, pg_sys::Datum
is no longer type Datum = usize;
, but a "newtype": a struct wrapping a pointer that indicates it is an opaque type. This is for correctness and to better represent the unique nature of the type with respect to Postgres. A fair amount of your code may have relied on T as pg_sys::Datum
or datum as T
working. Certainly some in pgx
did, resulting in patterns like:
// generating fresh arrays for data
let mut datums: Vec<pg_sys::Datum> = vec![0; N];
let mut nulls = vec![false; N];
// treating a datum as a pass-by-value type
let index = datum as i32;
// treating a datum as a pointer type
let varlena = datum as *mut pg_sys::varlena;
Now it doesn't! To make the transition easy, From<T> for pg_sys::Datum
is implemented for everything it is reasonable to convert directly into it in a "by-value" fashion. Use IntoDatum
for anything more complex. To get the usize
hiding inside Datum
out, use Datum::value(self) -> usize
, to cast it as a pointer, Datum::cast_mut_ptr::<T>(self) -> *mut T
is available.
// (getting|putting) data (from|into) Postgres as a datum array
let mut datums = vec![pg_sys::Datum::from(0); N];
let mut nulls = vec![false; N];
// treating a datum as a pass-by-value type
let index = datum.value() as i32;
// treating a datum as a pointer type
let varlena = datum.cast_mut_ptr::<pg_sys::varlena>();
Because a pg_sys::Datum
is a union of types, only certain traits that are implemented on usize
are also implemented on Datum
, as it was deemed safest to limit implementations to those that are also valid if Datum
is a pointer or float. This can induce code to reveal any assumptions it was making.
If you were an early upgrader to 0.5.0-beta.0
: First, thanks for trying things out! Second, you may have used Datum::ptr_cast
: it has the new name of cast_mut_ptr
. Datum::to_void
was simply dropped as it is unlikely to be what you want, and if it is, cast_mut_ptr::<c_void>
works.
FromDatum::from_polymorphic_datum
FromDatum::from_polymorphic_datum
now holds the behavior of FromDatum::from_datum
and a new FromDatum::from_datum
which only accepts 2 arguments (omitting the pg_sys::Oid
argument) has been added. By default, the new from_datum
calls from_polymorphic_datum
with pg_sys::InvalidOid
as the third argument. Most people use the provided implementations, but you should override this if you have a custom impl of FromDatum
for a polymorphic-like type like AnyElement
, or ignore the third parameter in your implementation of FromDatum::from_polymorphic_datum
if you don't.
Otherwise, you should be fine with a find-replace for the most part.
Date/Time types
Previously, pgx
leaned on the excellent support for dates and times provided by the time
crate. Unfortunately, that also meant that we ran into problems like "not representing all time values that Postgres understands". It also meant using heavy conversions when touching these types, even to just copy them out of Postgres, resulting in large amounts of switching between Rust and Postgres during control flow for e.g. constructing a Vec<Timestamp>
from a pg_sys::ArrayType
that was a handle to a varlena of pg_sys::Timestamp
. To allow fixing these performance and correctness problems, pgx
now implements these types in terms of the Postgres representations in Rust code.
This also means that all the {Date,Time,Timestamp}{,WithTimeZone}::new
functions are now deprecated.
For easy transition, {,Try}{Into,From}
for types in the time
crate are available with pgx { version = "0.5.0.beta-1", features = ["time-crate"] }
.
With thanks to @mhov, @workingjubilee, and @jsaied99's contributions:
- Opaque Date type with +/- infinity support by @mhov in #622
- Opaque Timestamp/Tz types by @mhov in #643
- Match the Postgres repr in Time and TimeWithTimeZone by @workingjubilee in #677
- Adding Clone to Timestamp and Date types by @jsaied99 in #700
Set/Table-returning functions
Functions that previously would be RETURNS SET OF
or RETURNS TABLE
used to return impl Iterator
. Unfortunately, not being able to name the type of the iterator greatly complicated pgx 0.5.0
's redesign for SQL generation lead by @Hoverbear and @workingjubilee. pgx::iter::SetOfIterator
and pgx::iter::TableIterator
now need to be used instead to return these values. In all existing cases you should be able to simply wrap the previous expression in {SetOf,Table}Iterator::new
, but for cases where you are returning a single row, TableIterator::once
makes for a sweeter alternative.
For example, this:
#[pg_extern]
fn fluffy() -> impl Iterator<Item = i32> {
vec![1,2,3].into_iter()
}
Becomes this:
#[pg_extern]
fn fluffy() -> SetOfIterator<'static, i32> {
SetOfIterator::new(vec![1,2,3].into_iter())
}
Array soundness issues
There were several soundness issues regarding interactions between the several ways of constructing pgx::datum::Array<'a, T>
, Array::as_slice
, and impl<'a, T> Drop for Array<'a, T>
. While the critical soundness issue for Drop has been fixed and the resulting leak plugged, these have resulted in the deprecation ofArray::over
and Array::as_slice
.
Array::as_slice
allowed wildly incorrect slices, or viewing data Postgres had marked as "null" in the SQL sense. Instead, this function now panics if either of these conditions would be met, or returns a newly-correct slice for simple data types. Because the usually-trivial fn as_slice
panicking is rarely expected, this function is deprecated.
Array::over
allows constructing improper Arrays from pointers to random data that is probably controlled by Rust and not Postgres, and thus is data in a form Rust prefers, when Array is supposed to be a zero-copy type that handles ArrayType data in the form Postgres prefers. This makes it almost impossible for the underlying type to be useful for both cases without severely impacting correctness and performance.
Both expose implications about the way that Postgres represents data that are not always true. If you still want to interact with the underlying representation of a Postgres Array and you know the Array was correctly constructed, consider the new experimental pgx::array::RawArray
type, created with support from bitvec
. It is possible pgx::datum::Array<'a, T>
may be replaced entirely in the future by a new type that exposes less assumptions about internal repr.
New features and fixes
In general, PGX added significant improvements for working with uncommon use-cases or existing configurations, with thanks to @steve-chavez, @anth0nyleung, and @TimeToogo.
We also moved some code into a new crate: pgx-pg-config
.
Fixes in cargo pgx
and pgx-pg-sys
- Hang onto libraries by @Hoverbear in #573
Acargo pgx
bug that could cause segfaults on old versions of glibc was fixed by no longer usingdlclose
on the libraries we dynamically load until the process ends.
We also found and fixed some unsound behavior in the way PGX handled symbols on MacOS thanks to @Smittyvb. T...
v0.5.0-beta.1
This is a pilot release for 0.5.0 and no further functional changes are intended from now until the 0.5.0 release. Bikeshedding, renaming, and purely architectural/internal rearrangements may still occur, but the only things anyone should have to change would be within the scope of simple find-replace rules. Bugfixes and other non-functional changes will be merged. We do not intend to merge any additional new features.
For newer users
Code written using pgx can now use pgx::prelude::*;
instead of use pgx::*;
and in many cases this will make the extension compile with only a few additional explicit imports. Existing extensions may require extra effort and may want to approach this more incrementally.
Upgrading
Most of the transition should be smooth, except for certain extensions. You will need to reinstall cargo pgx
first: everything regarding SQL generation changed internally, and cargo pgx is the binary that handles most of the actual SQL compilation. We now recommend using cargo install --locked cargo-pgx --version 0.5.0-beta.1
for this.
There are three major pain points you may immediately encounter: code that directly handles datums, date/time types, and set-returning or table-returning functions. But after that compiles, you will also want to address any soundness or behavior questions that might arise regarding Arrays in your code.
Handling Datums
Since 0.5.0-beta.0
, pg_sys::Datum
is no longer type Datum = usize;
, but a "newtype": a struct wrapping a pointer that indicates it is an opaque type. This is for correctness and to better represent the unique nature of the type with respect to Postgres. A fair amount of your code may have relied on T as pg_sys::Datum
or datum as T
working. Certainly some in pgx
did, resulting in patterns like:
// generating fresh arrays for data
let mut datums: Vec<pg_sys::Datum> = vec![0; N];
let mut nulls = vec![false; N];
// treating a datum as a pass-by-value type
let index = datum as i32;
// treating a datum as a pointer type
let varlena = datum as *mut pg_sys::varlena;
Now it doesn't! To make the transition easy, From<T> for pg_sys::Datum
is implemented for everything it is reasonable to convert directly into it in a "by-value" fashion. Use IntoDatum
for anything more complex. To get the usize
hiding inside Datum
out, use Datum::value(self) -> usize
, to cast it as a pointer, Datum::cast_mut_ptr::<T>(self) -> *mut T
is available.
// (getting|putting) data (from|into) Postgres as a datum array
let mut datums = vec![pg_sys::Datum::from(0); N];
let mut nulls = vec![false; N];
// treating a datum as a pass-by-value type
let index = datum.value() as i32;
// treating a datum as a pointer type
let varlena = datum.cast_mut_ptr::<pg_sys::varlena>();
Because a pg_sys::Datum
is a union of types, only certain traits that are implemented on usize
are also implemented on Datum
, as it was deemed safest to limit implementations to those that are also valid if Datum
is a pointer or float. This can induce code to reveal any assumptions it was making.
If you were an early upgrader to 0.5.0-beta.0
: First, thanks for trying things out! Second, you may have used Datum::ptr_cast
: it has the new name of cast_mut_ptr
. Datum::to_void
was simply dropped as it is unlikely to be what you want, and if it is, cast_mut_ptr::<c_void>
works.
Date/Time types
Previously, pgx
leaned on the excellent support for dates and times provided by the time
crate. Unfortunately, that also meant that we ran into problems like "not representing all time values that Postgres understands". It also meant using heavy conversions when touching these types, even to just copy them out of Postgres, resulting in large amounts of switching between Rust and Postgres during control flow for e.g. constructing a Vec<Timestamp>
from a pg_sys::ArrayType
that was a handle to a varlena of pg_sys::Timestamp
. To allow fixing these performance and correctness problems, pgx
now implements these types in terms of the Postgres representations in Rust code.
This also means that all the {Date,Time,Timestamp}{,WithTimeZone}::new
functions are now deprecated.
For easy transition, {,Try}{Into,From}
for types in the time
crate are available with pgx { version = "0.5.0.beta-1", features = ["time-crate"] }
.
With thanks to @mhov, @workingjubilee, and @jsaied99's contributions:
- Opaque Date type with +/- infinity support by @mhov in #622
- Opaque Timestamp/Tz types by @mhov in #643
- Match the Postgres repr in Time and TimeWithTimeZone by @workingjubilee in #677
- Adding Clone to Timestamp and Date types by @jsaied99 in #700
Set/Table-returning functions
Functions that previously would be RETURNS SET OF
or RETURNS TABLE
used to return impl Iterator
. Unfortunately, not being able to name the type of the iterator greatly complicated pgx 0.5.0
's redesign for SQL generation lead by @Hoverbear and @workingjubilee. pgx::iter::SetOfIterator
and pgx::iter::TableIterator
now need to be used instead to return these values. In all existing cases you should be able to simply wrap the previous expression in {SetOf,Table}Iterator::new
, but for cases where you are returning a single row, TableIterator::once
makes for a sweeter alternative.
For example, this:
#[pg_extern]
fn fluffy() -> impl Iterator<Item = i32> {
vec![1,2,3].into_iter()
}
Becomes this:
#[pg_extern]
fn fluffy() -> SetOfIterator<'static, i32> {
SetOfIterator::new(vec![1,2,3].into_iter())
}
Array soundness issues
There were several soundness issues regarding interactions between the several ways of constructing pgx::datum::Array<'a, T>
, Array::as_slice
, and impl<'a, T> Drop for Array<'a, T>
. While the critical soundness issue for Drop has been fixed and the resulting leak plugged, these have resulted in the deprecation ofArray::over
and Array::as_slice
.
Array::as_slice
allowed wildly incorrect slices, or viewing data Postgres had marked as "null" in the SQL sense. Instead, this function now panics if either of these conditions would be met, or returns a newly-correct slice for simple data types. Because the usually-trivial fn as_slice
panicking is rarely expected, this function is deprecated.
Array::over
allows constructing improper Arrays from pointers to random data that is probably controlled by Rust and not Postgres, and thus is data in a form Rust prefers, when Array is supposed to be a zero-copy type that handles ArrayType data in the form Postgres prefers. This makes it almost impossible for the underlying type to be useful for both cases without severely impacting correctness and performance.
Both expose implications about the way that Postgres represents data that are not always true. If you still want to interact with the underlying representation of a Postgres Array and you know the Array was correctly constructed, consider the new experimental pgx::array::RawArray
type, created with support from bitvec
. It is possible pgx::datum::Array<'a, T>
may be replaced entirely in the future by a new type that exposes less assumptions about internal repr.
New features and fixes
In general, PGX added significant improvements for working with uncommon use-cases or existing configurations, with thanks to @steve-chavez, @anth0nyleung, and @TimeToogo.
This includes a soundness fix for the way PGX handled symbols on MacOS thanks to @Smittyvb. This should fix a number of random crashes users were experiencing, but we can't tell for sure (by definition: UB!). Please give it a try and let us know if there are any issues remaining.
We also moved some code into a new crate: pgx-pg-config
.
Better soundness
@willmurnane contributed several soundness and correctness improvements, allowing input functions to validate or reject input (now accepting Options).
BackgroundWorker functions may now panic if used from unregistered workers. Thanks to @EdMcBane for catching the previously unsound behavior.
Optional CREATE OR REPLACE FUNCTION
In 0.4.5, PGX switched to using CREATE FUNCTION
by default, as this is nondestructive and more secure. However, that prevented migration beyond 0.4.4 for some users, [as they relied on CREATE OR ...
v0.5.0-beta.0
This is an experimental version for the upcoming 0.5.0 release.
Make sure to run cargo install --locked cargo-pgx --version 0.5.0-beta.0
.
Handling Datums
pg_sys::Datum
is no longer type Datum = usize;
, but a "newtype": a struct wrapping a pointer that indicates it is an opaque type. This is for correctness and to better represent the unique nature of the type with respect to Postgres. A fair amount of your code may have relied on T as pg_sys::Datum
or datum as T
working. Certainly some in pgx
did, resulting in patterns like:
// generating fresh arrays for data
let mut datums: Vec<pg_sys::Datum> = vec![0; N];
let mut nulls = vec![false; N];
// treating a datum as a pass-by-value type
let index = datum as i32;
// treating a datum as a pointer type
let varlena = datum as *mut pg_sys::varlena;
Now it doesn't! To make the transition easy, From<T> for pg_sys::Datum
is implemented for everything it is reasonable to convert directly into it in a "by-value" fashion. Use IntoDatum
for anything more complex. To get the usize
hiding inside Datum
out, use Datum::value(self) -> usize
, to cast it as a pointer, Datum::ptr_cast::<T>(self) -> *mut T
is available.
// (getting|putting) data (from|into) Postgres as a datum array
let mut datums = vec![pg_sys::Datum::from(0); N];
let mut nulls = vec![false; N];
// treating a datum as a pass-by-value type
let index = datum.value() as i32;
// treating a datum as a pointer type
let varlena = datum.ptr_cast::<pg_sys::varlena>();
Because a pg_sys::Datum
is a union of types, only certain traits that are implemented on usize
are also implemented on Datum
, as it was deemed safest to limit implementations to those that are also valid if Datum
is a pointer or float. This can induce code to reveal any assumptions it was making.
Enhancements
Considerable enhancements have been made to heap tuple and trigger support, introducing pg_trigger
and a new PgHeapTuple
type! Try them out!
- Improved "HeapTuple" support by @eeeebbbbrrrr in #532
- Trigger support improvements by @Hoverbear in #558
Fixes
- Hang onto libraries by @Hoverbear in #573
Acargo pgx
bug that could cause segfaults on old versions of glibc was fixed by no longer usingdlclose
on the libraries we dynamically load until the process ends.
Experimental features
You may have noticed the "postgrestd"
feature. This is a highly experimental feature for using PGX to back a very special configuration of Rust as a trusted procedural language: PL/Rust. It's best to assume this feature can induce unsound changes if they aren't combined with the rest of the configuration for the trusted language handler's building and running of functions.
Full Changelog: v0.4.5...v0.5.0-beta.0
v0.4.5
This is pgx v0.4.5
It's generally a minor release without backwards incompatible changes.
As usual, make sure to run cargo install cargo-pgx
.
What's Changed
- Lockdown semver on pgx deps by @Hoverbear in #559
- Annotate and refactor pgx-tests by @workingjubilee in #563
- Clone less while beginning to unwind by @workingjubilee in #564
- Do not use CREATE OR REPLACE FUNCTION by @Hoverbear in #554
- Remove dubious thread assertion by @workingjubilee in #562
- Pre-patch fixes by @workingjubilee in #568
- Bump to v0.4.5 by @workingjubilee in #569
Full Changelog: v0.4.4...v0.4.5
v0.4.4
This is pgx v0.4.4. A minor release which adds support for "versioned .so" files.
Notable Changes
- Optionally emit versioned .so by @JamesGuthrie in #546
- Add
impl Debug
forNumeric
by @Hoverbear in #551 - Fix
namespace.rs
safety issues by @eeeebbbbrrrr in #553 - Add "parser/parse_oper.h" to includes by @JamesGuthrie in #549
Minor Changes
- Fix spelling mistakes by @kiwicopple in #548
- Fix url typo on Detailed
cargo pgx
usage section by @msAlcantara in #550 - Add aggregate article by @Hoverbear in #555
New Contributors
- @kiwicopple made their first contribution in #548
- @msAlcantara made their first contribution in #550
Full Changelog: v0.4.3...v0.4.4