From 786b4cd4130fc8e9c6debd73dd4dbde493df6ce6 Mon Sep 17 00:00:00 2001 From: "Joshua D. Drake" Date: Mon, 6 Jul 2026 21:21:26 -0600 Subject: [PATCH] Release 2.5.0: $_SD, bytea binary, SPI colmeta, ltree transform PL/Python parity release. Bumps default_version to 2.5 with the standard no-op version move (all core 2.5 changes are in the shared library): - $_SD per-function static storage (PL/Python SD; $_SHARED is GD) - bytea <-> binary String mapping (PL/Python bytes; breaking) - spi_colnames/spi_coltypes/spi_coltypmods result metadata - the ltree_plruby transform ships as a separate extension Adds plruby--2.5.sql (copy of 2.4; SQL objects unchanged) and the no-op plruby--2.4--2.5.sql upgrade script; dates the CHANGELOG; test badge 42 -> 44. Verified on PG 18: full suite (44 tests) green, all three transform suites green, and the CREATE EXTENSION '2.0' -> ALTER EXTENSION UPDATE chain lands on 2.5. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 8 +++++++- Makefile | 2 +- README.md | 6 +++--- plruby--2.4--2.5.sql | 11 +++++++++++ plruby--2.5.sql | 32 ++++++++++++++++++++++++++++++++ plruby.control | 2 +- 6 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 plruby--2.4--2.5.sql create mode 100644 plruby--2.5.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index 955d944..d362a35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,13 @@ All notable changes to PL/Ruby are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project aims to follow [Semantic Versioning](https://semver.org/). -## [Unreleased] +## [2.5.0] - 2026-07-06 + +PL/Python parity: per-function `$_SD` storage, a raw-binary `bytea` mapping, SPI +result column metadata, and an `ltree` transform. With these, PL/Ruby is at or +ahead of PL/Python across the board. The core changes are in the shared library; +`ALTER EXTENSION plruby UPDATE` completes the upgrade after installing the new +binary. The `ltree` transform ships as the separate `ltree_plruby` extension. ### Added diff --git a/Makefile b/Makefile index 4283b5d..c709ae4 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ MODULE_big = plruby OBJS = plruby.o plruby_io.o plruby_spi.o EXTENSION = plruby -DATA = plruby--2.0.sql plruby--2.1.sql plruby--2.2.sql plruby--2.3.sql plruby--2.4.sql plruby--2.0--2.1.sql plruby--2.1--2.2.sql plruby--2.2--2.3.sql plruby--2.3--2.4.sql +DATA = plruby--2.0.sql plruby--2.1.sql plruby--2.2.sql plruby--2.3.sql plruby--2.4.sql plruby--2.5.sql plruby--2.0--2.1.sql plruby--2.1--2.2.sql plruby--2.2--2.3.sql plruby--2.3--2.4.sql plruby--2.4--2.5.sql # Ruby compile/link flags, discovered via RbConfig. RUBY ?= ruby diff --git a/README.md b/README.md index 0114fab..381011a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![CI](https://github.com/commandprompt/plruby/actions/workflows/ci.yml/badge.svg)](https://github.com/commandprompt/plruby/actions/workflows/ci.yml) [![PostgreSQL](https://img.shields.io/badge/PostgreSQL-11_to_18-336791?logo=postgresql&logoColor=white)](https://www.postgresql.org/) [![Ruby](https://img.shields.io/badge/Ruby-3.x-CC342D?logo=ruby&logoColor=white)](https://www.ruby-lang.org/) -[![Tests](https://img.shields.io/badge/tests-42_passing-brightgreen)](sql/) +[![Tests](https://img.shields.io/badge/tests-44_passing-brightgreen)](sql/) [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE) @@ -45,11 +45,11 @@ SELECT hello('world'); -- Hello, world! | 🔁 **Set-returning functions** | `RETURNS SETOF` / `RETURNS TABLE` with `return_next`. | | ⚡ **Triggers** | Row & statement triggers via `$_TD` (with `'SKIP'` / `'MODIFY'`). | | 📣 **Event triggers** | Back `CREATE EVENT TRIGGER` with `RETURNS event_trigger`. | -| 🗄️ **Database access (SPI)** | `spi_exec`, `spi_fetch_row`, `spi_processed`, `spi_status`, `spi_rewind`. | +| 🗄️ **Database access (SPI)** | `spi_exec`, `spi_fetch_row`, `spi_processed`, `spi_status`, `spi_rewind`, and result column metadata (`spi_colnames` / `spi_coltypes` / `spi_coltypmods`). | | 🌊 **Cursor streaming** | `spi_query` (block or handle), `spi_fetchrow`, `spi_cursor_close`, `Cursor#each`. Consume large results without materializing them. | | 📝 **Prepared statements** | `spi_prepare` / `spi_exec_prepared` / `spi_query_prepared` / `spi_freeplan`. | | 🔐 **Transaction control** | `spi_commit` / `spi_rollback` in procedures, plus `subtransaction` blocks. | -| 🧰 **Utilities** | `quote_literal` / `quote_nullable` / `quote_ident`, `elog`, `$_SHARED`. | +| 🧰 **Utilities** | `quote_literal` / `quote_nullable` / `quote_ident`, `elog`, session-shared `$_SHARED`, and per-function `$_SD`. | | 📦 **Session setup** | Anonymous `DO` blocks, `plruby_modules` autoloading, and a `plruby.start_proc` hook. | | 🔄 **Transforms** | `jsonb_plruby`, `hstore_plruby`, and `ltree_plruby`: functions declared `TRANSFORM FOR TYPE` exchange native Ruby Hashes/Arrays with `jsonb`, `hstore`, and `ltree`. | diff --git a/plruby--2.4--2.5.sql b/plruby--2.4--2.5.sql new file mode 100644 index 0000000..4bb6282 --- /dev/null +++ b/plruby--2.4--2.5.sql @@ -0,0 +1,11 @@ +/* Upgrade PL/Ruby from 2.4 to 2.5. + * + * Every 2.5 change lives in the shared library ($_SD per-function storage, the + * bytea<->binary String mapping, and the spi_colnames/spi_coltypes/ + * spi_coltypmods result accessors); the ltree transform is a separate + * extension (ltree_plruby). The core extension's SQL-level objects are + * unchanged, so this script has nothing to do beyond moving the version. + */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION plruby UPDATE TO '2.5'" to load this file. \quit diff --git a/plruby--2.5.sql b/plruby--2.5.sql new file mode 100644 index 0000000..b445f8a --- /dev/null +++ b/plruby--2.5.sql @@ -0,0 +1,32 @@ +/* PL/Ruby language, packaged as an extension. + * + * The language is UNTRUSTED (created without the TRUSTED attribute): on modern + * Ruby there is no sandbox ($SAFE was removed in Ruby 3.0), so PL/Ruby + * functions can do anything the server's OS user can. Creating them is + * therefore restricted to superusers. + */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION plruby" to load this file. \quit + +CREATE FUNCTION plruby_call_handler() +RETURNS language_handler +AS 'MODULE_PATHNAME' +LANGUAGE C; + +CREATE FUNCTION plruby_inline_handler(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C; + +CREATE FUNCTION plruby_validator(oid) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C; + +CREATE LANGUAGE plruby + HANDLER plruby_call_handler + INLINE plruby_inline_handler + VALIDATOR plruby_validator; + +COMMENT ON LANGUAGE plruby IS 'PL/Ruby procedural language (untrusted)'; diff --git a/plruby.control b/plruby.control index 7ea378b..1baa248 100644 --- a/plruby.control +++ b/plruby.control @@ -6,6 +6,6 @@ # superuser-only to install and the language is created without the TRUSTED # attribute. comment = 'PL/Ruby procedural language (untrusted)' -default_version = '2.4' +default_version = '2.5' module_pathname = '$libdir/plruby' relocatable = false