Skip to content

Releases: commandprompt/plx

plx 1.3.1

Choose a tag to compare

@jdatcmd jdatcmd released this 16 Jul 23:08

Code-only patch release (no catalog changes) carrying the memory-safety and robustness fixes from the full-repo transpiler audit (#1). Upgrade with ALTER EXTENSION plx UPDATE TO '1.3.1' after installing the new module.

Fixed

  • Missing capacity guard on the trailing T_EOF token write in lex() (heap overflow / SIGSEGV when a source lexed to exactly cap-1 tokens).
  • plx_strbuild sb_ensure() int32 doubling could wrap negative near ~1GB and spin while passing a bogus size to repalloc; growth is now 64-bit and clamped to MaxAllocSize.
  • The recursion-guarded transpiler entries now call check_stack_depth(), so deeply nested input raises a clean error (honoring max_stack_depth) instead of crashing the backend.
  • The Python lexer raises a clean "indentation nested too deeply" error at the indent-stack limit instead of emitting an unbalanced T_INDENT.
  • Raw single-quoted strings in Ruby and PHP keep backslashes literal (only \\ and \' are special).
  • PHP ${name} curly interpolation in double-quoted strings is now recognized.
  • Non-decimal integer literals (0x/0o/0b, with _ separators) are lexed as one token and rewritten to decimal (portable to PG13-15); a >64-bit literal raises a clean "integer literal out of range" error.

Other

  • Declare the built-in dialect descriptors in plx.h, clearing -Wmissing-variable-declarations.

Verified against PostgreSQL 18.4: clean build, all 13 installcheck tests pass, and the 1.3.0 → 1.3.1 upgrade applies cleanly.

plx 1.3.0

Choose a tag to compare

@jdatcmd jdatcmd released this 15 Jul 23:40

plx 1.3.0 makes trigger row mutation available across the dialects and ships a verified cookbook for every dialect.

Added

  • plxtsql trigger row mutation. A Transact-SQL trigger can now assign to NEW fields with SET NEW.col = e, which lowers to NEW.col := e, so a trigger can rewrite the row and not only validate it. A SET with a qualified target and a top-level = is an assignment; SET NOCOUNT ON and other session options are still ignored. With the plxphp arrow assignment added in 1.2.2, assigning to a trigger's NEW fields is now supported across the dialects, each in its own idiom.
  • Cookbooks and limitations docs. A verified, runnable cookbook for each of the nine dialects (scalar functions, loops, string building, query loops, set-returning functions, error handling, triggers, dynamic SQL, and dialect idioms), and a consolidated gaps-and-limitations page. Both are on the documentation site.

No catalog changes. All 13 regression suites pass on PostgreSQL 13 through 18, plus 19beta and 20devel built from source.

Upgrade

Install the new module (make && make install), then:

ALTER EXTENSION plx UPDATE TO '1.3.0';

A fresh CREATE EXTENSION plx lands on 1.3.0 directly. The PGXN distribution zip (plx-1.3.0.zip) is attached.

plx 1.2.2

Choose a tag to compare

@jdatcmd jdatcmd released this 15 Jul 23:02

A code-only patch release.

Fixed

  • plxphp: assigning to a record field with the arrow form ($NEW->col = e), the idiomatic PHP spelling, previously raised "unsupported operator in statement". It now lowers to NEW.col := e, so a trigger function can stamp NEW fields with $NEW->col = e. The array-element form ($NEW['col'] = e) continues to work.

No catalog changes. The full 13-suite regression passes on PostgreSQL 13 through 18, plus 19beta2 and 20devel built from source.

Upgrade

Install the new module (make && make install), then:

ALTER EXTENSION plx UPDATE TO '1.2.2';

A fresh CREATE EXTENSION plx lands on 1.2.2 directly. The PGXN distribution zip (plx-1.2.2.zip) is attached.

See CHANGELOG.md.

plx 1.2.1

Choose a tag to compare

@jdatcmd jdatcmd released this 15 Jul 21:19

A code-only patch release: plx now builds on PostgreSQL 19 and 20.

Fixed

  • Build on PostgreSQL 19 and 20 with a C23 toolchain (for example gcc 15). There, PostgreSQL defines pg_noreturn as the standard [[noreturn]] attribute, whose placement is strict. plx wrote it after the storage class (static pg_noreturn void ...), which C23 rejects, so plx did not compile on 19/20. It is now the first token of each declaration (pg_noreturn static void ...), matching PostgreSQL's own convention, and still compiles on 13 through 18.

The full 13-suite regression passes on PostgreSQL 13 through 18, plus 19beta2 and 20devel built from source. No catalog changes: the only change is in the loadable module.

Upgrade

Install the new module (make && make install), then:

ALTER EXTENSION plx UPDATE TO '1.2.1';

A fresh CREATE EXTENSION plx lands on 1.2.1 directly. The PGXN distribution zip (plx-1.2.1.zip) is attached.

See CHANGELOG.md.

plx 1.2

Choose a tag to compare

@jdatcmd jdatcmd released this 15 Jul 18:27

plx 1.2 makes it nine dialects. Write a PostgreSQL function body in the language you already know; plx transpiles it to plpgsql at CREATE FUNCTION time and the standard plpgsql interpreter runs it. No language runtime is loaded into the backend, and the generated plpgsql is visible in the catalog.

Dialects (9)

plxruby · plxphp · plxjs · plxts (TypeScript) · plxpython3 · plxgo (Go) · plxcobol · plxplsql (Oracle PL/SQL) · plxtsql (Transact-SQL / SQL Server)

New since 1.1

  • Four new dialects: Oracle PL/SQL, Transact-SQL (SQL Server), Go, and TypeScript. The SQL-family and Go dialects are restructuring front ends (own tokenizers/parsers); PL/SQL and TypeScript build on the near-plpgsql and JavaScript paths. See each chapter under doc/.
  • COBOL tables: OCCURS n maps a WORKING-STORAGE item to a PostgreSQL array, with WS-ARR(i) subscripts and PERFORM v OVER ARRAY iteration.
  • plpgsql completeness audit across dialects (OUT/INOUT/RETURNS TABLE/STRICT), a worked examples/ directory, and doc/DEBUGGING.md + a plx_source() helper.
  • Whole-project hardening: a fresh-eyes review of every front end plus mutation fuzzing of all nine dialects fixed real backend crashes, hangs, and wrong/invalid-output cases. The fuzzer (test/fuzz.py) and corpus now cover all nine dialects and are crash- and hang-clean.

Compatibility

All 13 regression suites pass on PostgreSQL 13 through 18 (CI + local matrix). plx_strbuild's in-place fast path (amortized-O(1) string append) is accelerated on PostgreSQL 18; correct but unaccelerated on 13–17.

Install

Build from source (make && make install), then CREATE EXTENSION plx;. Upgrade from an earlier install with ALTER EXTENSION plx UPDATE TO '1.2';. A PGXN distribution zip (plx-1.2.0.zip) is attached.

See CHANGELOG.md for the full list.

plx 1.1.1

Choose a tag to compare

@jdatcmd jdatcmd released this 15 Jul 13:05

plx 1.1.1 is a code-only patch release (no catalog changes). It restores
compilation on PostgreSQL 13-15 and fixes several plxcobol bugs found in review.

Upgrade an existing install with:

ALTER EXTENSION plx UPDATE TO '1.1.1';

Fixed

  • Compilation on PostgreSQL 13, 14, and 15. plx_strbuild.c included
    varatt.h unconditionally, but that header was only split out of postgres.h
    in PostgreSQL 16, so 1.1 did not build on 13-15. The full 9-suite regression
    now passes on PostgreSQL 13 through 18 (verified in CI).
  • plxcobol crash (out-of-bounds read) on a body truncated at
    PERFORM VARYING ... UNTIL; it now errors cleanly.
  • plxcobol ADD a b GIVING c and other multi-addend ADD/SUBTRACT forms
    were rejected; they are parsed as operand lists now.
  • plxcobol multi-argument function calls (mod(a, b)) were broken because
    the tokenizer stripped commas everywhere; commas inside parentheses are kept.
  • plxcobol GREATER/LESS ... OR EQUAL at the end of a condition, a PICTURE
    repeat-count overflow, and unterminated string handling.

Added

  • Continuous integration (GitHub Actions) running the full suite on PostgreSQL
    13 through 18 (green).
  • plxcobol coverage in the fuzzer and corpus runner.
  • A PGXN META.json, and the plx-1.1.1.zip distribution attached to this
    release.

Compatibility

Builds and passes the full regression suite on PostgreSQL 13, 14, 15, 16, 17,
and 18.

plx 1.1

Choose a tag to compare

@jdatcmd jdatcmd released this 15 Jul 02:04

plx 1.1 adds plxcobol, a COBOL dialect (ISO/IEC 1989:2023, COBOL 2023, free
format), at full plpgsql construct parity. As with the other dialects, a COBOL
function body is transpiled to plpgsql at CREATE FUNCTION time and runs on the
standard plpgsql interpreter, with no separate language runtime in the backend.

plxcobol

COBOL is verb-driven and free-format, so it has its own front end (tokenizer and
recursive-descent parser). Data names map to plpgsql identifiers (lower-cased,
hyphens to underscores). Coverage:

  • WORKING-STORAGE declarations, with PICTURE mapped to SQL types, plus TYPE
    (for %ROWTYPE, RECORD, refcursor) and CONSTANT AS.
  • MOVE / COMPUTE and the ADD / SUBTRACT / MULTIPLY / DIVIDE verbs;
    ** is exponent and % is modulo.
  • IF / ELSE / END-IF; EVALUATE (simple and searched EVALUATE TRUE).
  • PERFORM in the UNTIL, VARYING, TIMES, inline, query (OVER "sql") and
    array (OVER ARRAY) forms; EXIT PERFORM [CYCLE].
  • GOBACK RETURNING, RETURN-NEXT, RETURN-QUERY; EXECUTE with USING/INTO;
    cursors (OPEN-CURSOR/FETCH-CURSOR/MOVE-CURSOR/CLOSE-CURSOR).
  • Exception handling (BEGIN-TRY/WHEN/END-TRY) with stacked diagnostics via
    GET; GET ROW-COUNT; FOUND.
  • STRING-APPEND <expr> TO <var>, which lowers to the plx_strbuild string
    builder (amortized-O(1) in-loop string building).
  • RAISE, DISPLAY, ASSERT, CALL, COMMIT/ROLLBACK.

See doc/plxcobol.md
and the parity matrix in
doc/PARITY.md.

Performance

plxcobol transpiles to plpgsql like the other dialects, so it matches plpgsql on
the arithmetic, iteration, string-building, and call workloads; see
bench/BENCHMARKS.md.

Upgrading

Existing 1.0 installations upgrade in place:

ALTER EXTENSION plx UPDATE TO '1.1';

A fresh CREATE EXTENSION plx installs 1.1 directly.

Compatibility

Tested against PostgreSQL 13 through 18; the full regression suite (nine suites,
including plxcobol) passes on each.

plx 1.0

Choose a tag to compare

@jdatcmd jdatcmd released this 15 Jul 01:02

plx lets you write PostgreSQL stored functions and triggers in a Ruby, PHP,
JavaScript, or Python dialect. At CREATE FUNCTION time the body is transpiled
to plpgsql and stored in pg_proc.prosrc; at run time it executes on the
standard plpgsql interpreter, with no separate language runtime in the backend.

Highlights

  • Dialect-pluggable front end (growing set): plxruby, plxphp, plxjs,
    plxpython3, each at full plpgsql construct parity. Language names carry a
    plx prefix, so the extension coexists with native PL/Ruby and PL/PHP.
  • The generated plpgsql is visible in pg_proc.prosrc and re-transpile is
    idempotent (a sentinel comment records the version and embeds the original
    source).
  • plx_strbuild, an expanded-object string builder with amortized-O(1) append,
    addressing plpgsql's O(n^2) in-loop string concatenation. The dialect append
    operators (s << x, $s .= x, s += x on a string) lower onto it. On
    PostgreSQL 18 this is about 170x faster than s := s || 'x' and faster than
    the native PLs' own append; on PostgreSQL 13 to 17 it is correct but not
    accelerated (the in-place path needs a PostgreSQL 18 planner feature).
  • Benchmarks against plpgsql, the plx dialects, PL/Perl, PL/Python3, and native
    PL/Ruby and PL/PHP. Regression suite, corpus runner, and fuzzer.
  • Full documentation: per-dialect chapters, a plpgsql parity matrix, a user
    guide, an architecture document, and a transpiler specification.

Compatibility

Tested against PostgreSQL 13, 14, 15, 16, 17, and 18. The full regression suite
passes on each.

Install

make PG_CONFIG=/path/to/pg_config
make install PG_CONFIG=/path/to/pg_config
CREATE EXTENSION plx;

See the CHANGELOG
for the full list.