Skip to content

Commit 0f8d886

Browse files
plxclaude
andcommitted
Release 1.3.0: trigger row mutation across dialects + docs
Minor release. Adds plxtsql trigger NEW-field mutation (SET NEW.col = e), which with the plxphp arrow assignment (1.2.2) means assigning to a trigger NEW field is supported across dialects. Also folds in the per-dialect cookbooks and the gaps-and-limitations documentation set. No catalog changes: full plx--1.3.0.sql == 1.2.2, no-op plx--1.2.2--1.3.0.sql upgrade; default_version/META.json 1.3.0. Fresh install, upgrade from 1.2.2, and chained upgrade from 1.0 verified; all 13 suites pass on PostgreSQL 13 through 20. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent bf17a79 commit 0f8d886

6 files changed

Lines changed: 232 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ All notable changes to plx are recorded here. The format follows
44
[Keep a Changelog](https://keepachangelog.com/), and plx uses the extension
55
version in `plx.control` (currently `1.0`).
66

7-
## [Unreleased]
7+
## [1.3.0] - 2026-07-15
8+
9+
Trigger row mutation across dialects, plus the cookbook and limitations
10+
documentation set. Upgrade with `ALTER EXTENSION plx UPDATE TO '1.3.0'` after
11+
installing the new module (no catalog changes).
812

913
### Added
1014

@@ -14,6 +18,13 @@ version in `plx.control` (currently `1.0`).
1418
is an assignment; `SET NOCOUNT ON` and other session options are still ignored.
1519
Qualified names also emit without a stray space around the dot. Covered by a new
1620
plxtsql trigger regression test.
21+
- A verified cookbook for each of the nine dialects (`doc/cookbook/`) and a
22+
consolidated gaps-and-limitations page (`doc/LIMITATIONS.md`), both on the
23+
documentation site.
24+
25+
With the plxphp arrow assignment (1.2.2) and this plxtsql `SET NEW.col`, assigning
26+
to a trigger's `NEW` fields is supported across the dialects in the dialect's own
27+
idiom. See each dialect's cookbook trigger recipe.
1728

1829
## [1.2.2] - 2026-07-15
1930

META.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
"name": "plx",
33
"abstract": "Write PostgreSQL functions in Ruby, PHP, JavaScript, TypeScript, Python, Go, COBOL, Oracle PL/SQL, or Transact-SQL, compiled to plpgsql",
44
"description": "plx is a dialect-pluggable procedural language for PostgreSQL. A function body written in a Ruby, PHP, JavaScript, TypeScript, Python, Go, COBOL, Oracle PL/SQL, or Transact-SQL (SQL Server) dialect is transpiled to plpgsql at CREATE FUNCTION time and stored in pg_proc.prosrc, then executed by the standard plpgsql interpreter. There is no separate language runtime in the backend, the generated plpgsql is visible in the catalog, and every plpgsql construct is reachable from every dialect. plx also ships plx_strbuild, an expanded-object string builder with amortized-O(1) append that fixes plpgsql's quadratic in-loop string concatenation.",
5-
"version": "1.2.2",
5+
"version": "1.3.0",
66
"maintainer": [
77
"Command Prompt, Inc. <pgxn@commandprompt.com>"
88
],
99
"license": "mit",
1010
"provides": {
1111
"plx": {
1212
"abstract": "Dialect-pluggable procedural language over plpgsql (Ruby, PHP, JavaScript, TypeScript, Python, Go, COBOL, Oracle PL/SQL, Transact-SQL)",
13-
"file": "plx--1.2.2.sql",
13+
"file": "plx--1.3.0.sql",
1414
"docfile": "README.md",
15-
"version": "1.2.2"
15+
"version": "1.3.0"
1616
}
1717
},
1818
"prereqs": {

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ MODULE_big = plx
33
OBJS = src/plx_core.o src/plx_transpile.o src/plx_strbuild.o src/plx_dialect_ruby.o src/plx_dialect_php.o src/plx_dialect_js.o src/plx_dialect_python.o src/plx_dialect_cobol.o src/plx_dialect_plsql.o src/plx_dialect_ts.o src/plx_dialect_tsql.o src/plx_dialect_go.o
44

55
EXTENSION = plx
6-
DATA = plx--1.0.sql plx--1.1.sql plx--1.1.1.sql plx--1.2.sql plx--1.2.1.sql plx--1.2.2.sql plx--1.0--1.1.sql plx--1.1--1.1.1.sql plx--1.1.1--1.2.sql plx--1.2--1.2.1.sql plx--1.2.1--1.2.2.sql
6+
DATA = plx--1.0.sql plx--1.1.sql plx--1.1.1.sql plx--1.2.sql plx--1.2.1.sql plx--1.2.2.sql plx--1.3.0.sql plx--1.0--1.1.sql plx--1.1--1.1.1.sql plx--1.1.1--1.2.sql plx--1.2--1.2.1.sql plx--1.2.1--1.2.2.sql plx--1.2.2--1.3.0.sql
77

88
# pg_regress suite (make installcheck). test/run_corpus.py is an additional
99
# Ruby corpus runner.

plx--1.2.2--1.3.0.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* plx 1.2.2 -> 1.3.0: no catalog changes.
2+
*
3+
* 1.3.0 adds plxtsql trigger row mutation (SET NEW.col = e), which lives entirely
4+
* in the loadable module ($libdir/plx). No SQL objects the extension defines
5+
* change, so this update script only advances the recorded version. Installing
6+
* the matching $libdir/plx is what delivers the new behavior. */

plx--1.3.0.sql

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/* plx 1.0: registers the plx dialect languages and the string-builder type */
2+
3+
\echo Use "CREATE EXTENSION plx" to load this file. \quit
4+
5+
/*
6+
* plx_strbuild: an expanded-object string builder. Its flattened form is a
7+
* text-compatible varlena, so it casts to and from text without a function.
8+
* plx_sb_append grows the buffer in place across a loop (amortized O(1)),
9+
* avoiding the quadratic cost of `s := s || 'x'` on plain text.
10+
*/
11+
CREATE TYPE plx_strbuild;
12+
13+
CREATE FUNCTION plx_sb_in(cstring) RETURNS plx_strbuild
14+
AS '$libdir/plx', 'plx_sb_in' LANGUAGE C IMMUTABLE STRICT;
15+
CREATE FUNCTION plx_sb_out(plx_strbuild) RETURNS cstring
16+
AS '$libdir/plx', 'plx_sb_out' LANGUAGE C IMMUTABLE STRICT;
17+
18+
CREATE TYPE plx_strbuild (
19+
INPUT = plx_sb_in,
20+
OUTPUT = plx_sb_out,
21+
LIKE = text,
22+
STORAGE = extended
23+
);
24+
25+
CREATE FUNCTION plx_sb_append_support(internal) RETURNS internal
26+
AS '$libdir/plx', 'plx_sb_append_support' LANGUAGE C;
27+
28+
CREATE FUNCTION plx_sb_append(plx_strbuild, text) RETURNS plx_strbuild
29+
AS '$libdir/plx', 'plx_sb_append' LANGUAGE C IMMUTABLE
30+
SUPPORT plx_sb_append_support;
31+
32+
-- plx_strbuild is implicitly usable as text (so it works in RETURN, string
33+
-- functions, and concatenation). text becomes a builder only in assignment
34+
-- context, which avoids operator ambiguity such as `builder || text`.
35+
CREATE CAST (plx_strbuild AS text) WITHOUT FUNCTION AS IMPLICIT;
36+
CREATE CAST (text AS plx_strbuild) WITHOUT FUNCTION AS ASSIGNMENT;
37+
38+
/*
39+
* Runtime call handler = plpgsql's OWN handler. Binding a fresh pg_proc row to
40+
* plpgsql.so's exported symbol is legal (CreateProceduralLanguage only checks
41+
* the handler RETURNS language_handler). Execution is therefore 100% stock
42+
* plpgsql; plx contributes zero call-path C.
43+
*/
44+
CREATE FUNCTION plx_call_handler()
45+
RETURNS language_handler
46+
AS '$libdir/plpgsql', 'plpgsql_call_handler'
47+
LANGUAGE C;
48+
49+
/* Ruby dialect validator + inline handler live in plx.so */
50+
CREATE FUNCTION plx_ruby_validator(oid)
51+
RETURNS void
52+
AS '$libdir/plx', 'plx_ruby_validator'
53+
LANGUAGE C STRICT;
54+
55+
CREATE FUNCTION plx_ruby_inline_handler(internal)
56+
RETURNS void
57+
AS '$libdir/plx', 'plx_ruby_inline_handler'
58+
LANGUAGE C;
59+
60+
CREATE TRUSTED LANGUAGE plxruby
61+
HANDLER plx_call_handler
62+
INLINE plx_ruby_inline_handler
63+
VALIDATOR plx_ruby_validator;
64+
65+
COMMENT ON LANGUAGE plxruby IS 'plx Ruby dialect (transpiles to plpgsql)';
66+
67+
/* PHP dialect */
68+
CREATE FUNCTION plx_php_validator(oid)
69+
RETURNS void
70+
AS '$libdir/plx', 'plx_php_validator'
71+
LANGUAGE C STRICT;
72+
73+
CREATE FUNCTION plx_php_inline_handler(internal)
74+
RETURNS void
75+
AS '$libdir/plx', 'plx_php_inline_handler'
76+
LANGUAGE C;
77+
78+
CREATE TRUSTED LANGUAGE plxphp
79+
HANDLER plx_call_handler
80+
INLINE plx_php_inline_handler
81+
VALIDATOR plx_php_validator;
82+
83+
COMMENT ON LANGUAGE plxphp IS 'plx PHP dialect (transpiles to plpgsql)';
84+
85+
/* JavaScript dialect */
86+
CREATE FUNCTION plx_js_validator(oid)
87+
RETURNS void
88+
AS '$libdir/plx', 'plx_js_validator'
89+
LANGUAGE C STRICT;
90+
91+
CREATE FUNCTION plx_js_inline_handler(internal)
92+
RETURNS void
93+
AS '$libdir/plx', 'plx_js_inline_handler'
94+
LANGUAGE C;
95+
96+
CREATE TRUSTED LANGUAGE plxjs
97+
HANDLER plx_call_handler
98+
INLINE plx_js_inline_handler
99+
VALIDATOR plx_js_validator;
100+
101+
COMMENT ON LANGUAGE plxjs IS 'plx JavaScript dialect (transpiles to plpgsql)';
102+
103+
/* Python dialect */
104+
CREATE FUNCTION plx_py_validator(oid)
105+
RETURNS void
106+
AS '$libdir/plx', 'plx_py_validator'
107+
LANGUAGE C STRICT;
108+
109+
CREATE FUNCTION plx_py_inline_handler(internal)
110+
RETURNS void
111+
AS '$libdir/plx', 'plx_py_inline_handler'
112+
LANGUAGE C;
113+
114+
CREATE TRUSTED LANGUAGE plxpython3
115+
HANDLER plx_call_handler
116+
INLINE plx_py_inline_handler
117+
VALIDATOR plx_py_validator;
118+
119+
COMMENT ON LANGUAGE plxpython3 IS 'plx Python dialect (transpiles to plpgsql)';
120+
121+
/* COBOL dialect (ISO/IEC 1989:2023) validator + inline handler live in plx.so */
122+
CREATE FUNCTION plx_cob_validator(oid)
123+
RETURNS void
124+
AS '$libdir/plx', 'plx_cob_validator'
125+
LANGUAGE C STRICT;
126+
127+
CREATE FUNCTION plx_cob_inline_handler(internal)
128+
RETURNS void
129+
AS '$libdir/plx', 'plx_cob_inline_handler'
130+
LANGUAGE C;
131+
132+
CREATE TRUSTED LANGUAGE plxcobol
133+
HANDLER plx_call_handler
134+
INLINE plx_cob_inline_handler
135+
VALIDATOR plx_cob_validator;
136+
137+
COMMENT ON LANGUAGE plxcobol IS 'plx COBOL dialect (ISO/IEC 1989:2023, transpiles to plpgsql)';
138+
139+
/* PL/SQL dialect (Oracle) validator + inline handler live in plx.so */
140+
CREATE FUNCTION plx_plsql_validator(oid)
141+
RETURNS void
142+
AS '$libdir/plx', 'plx_plsql_validator'
143+
LANGUAGE C STRICT;
144+
145+
CREATE FUNCTION plx_plsql_inline_handler(internal)
146+
RETURNS void
147+
AS '$libdir/plx', 'plx_plsql_inline_handler'
148+
LANGUAGE C;
149+
150+
CREATE TRUSTED LANGUAGE plxplsql
151+
HANDLER plx_call_handler
152+
INLINE plx_plsql_inline_handler
153+
VALIDATOR plx_plsql_validator;
154+
155+
COMMENT ON LANGUAGE plxplsql IS 'plx Oracle PL/SQL dialect (transpiles to plpgsql)';
156+
157+
/* TypeScript dialect validator + inline handler live in plx.so */
158+
CREATE FUNCTION plx_ts_validator(oid)
159+
RETURNS void
160+
AS '$libdir/plx', 'plx_ts_validator'
161+
LANGUAGE C STRICT;
162+
163+
CREATE FUNCTION plx_ts_inline_handler(internal)
164+
RETURNS void
165+
AS '$libdir/plx', 'plx_ts_inline_handler'
166+
LANGUAGE C;
167+
168+
CREATE TRUSTED LANGUAGE plxts
169+
HANDLER plx_call_handler
170+
INLINE plx_ts_inline_handler
171+
VALIDATOR plx_ts_validator;
172+
173+
COMMENT ON LANGUAGE plxts IS 'plx TypeScript dialect (transpiles to plpgsql)';
174+
175+
/* T-SQL dialect (Transact-SQL) validator + inline handler live in plx.so */
176+
CREATE FUNCTION plx_tsql_validator(oid)
177+
RETURNS void
178+
AS '$libdir/plx', 'plx_tsql_validator'
179+
LANGUAGE C STRICT;
180+
181+
CREATE FUNCTION plx_tsql_inline_handler(internal)
182+
RETURNS void
183+
AS '$libdir/plx', 'plx_tsql_inline_handler'
184+
LANGUAGE C;
185+
186+
CREATE TRUSTED LANGUAGE plxtsql
187+
HANDLER plx_call_handler
188+
INLINE plx_tsql_inline_handler
189+
VALIDATOR plx_tsql_validator;
190+
191+
COMMENT ON LANGUAGE plxtsql IS 'plx Transact-SQL (SQL Server) dialect (transpiles to plpgsql)';
192+
193+
/* Go dialect validator + inline handler live in plx.so */
194+
CREATE FUNCTION plx_go_validator(oid)
195+
RETURNS void
196+
AS '$libdir/plx', 'plx_go_validator'
197+
LANGUAGE C STRICT;
198+
199+
CREATE FUNCTION plx_go_inline_handler(internal)
200+
RETURNS void
201+
AS '$libdir/plx', 'plx_go_inline_handler'
202+
LANGUAGE C;
203+
204+
CREATE TRUSTED LANGUAGE plxgo
205+
HANDLER plx_call_handler
206+
INLINE plx_go_inline_handler
207+
VALIDATOR plx_go_validator;
208+
209+
COMMENT ON LANGUAGE plxgo IS 'plx Go dialect (transpiles to plpgsql)';

plx.control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
comment = 'plx (plExcellent): dialect-pluggable procedural language over plpgsql'
2-
default_version = '1.2.2'
2+
default_version = '1.3.0'
33
module_pathname = '$libdir/plx'
44
relocatable = true

0 commit comments

Comments
 (0)