PL/php vs PL/Tcl feature comparison

This compares PL/php against PostgreSQL’s built-in PL/Tcl. Items marked added were implemented to match PL/Tcl; the one remaining gap is noted with its rationale.

Language capabilities

Capability PL/Tcl PL/php Notes
Scalar / composite / array functions
Set-returning functions return_next
DML trigger functions $_TD in PL/php; $TG_*/$NEW/$OLD in PL/Tcl
Event trigger functions added RETURNS event_trigger; $_TD['event'], $_TD['tag']
Session-shared data GD array $_SHARED
Private per-function data $_SD added like PL/Python’s SD ($_SHARED is the GD counterpart)
Transaction control in procedures commit/rollback spi_commit/spi_rollback
Explicit subtransactions subtransaction {…} subtransaction(callable, …) added
Module autoloading pltcl_modules + unknown plphp_modules added PL/php eager-loads all module rows at interpreter init
Start proc pltcl.start_proc plphp.start_proc added
Trusted (sandboxed) variant pltcl (Safe-Tcl) ❌ by design see below

Built-in commands / functions

PL/Tcl PL/php Notes
spi_exec ?-count n? cmd spi_exec(cmd [, limit])
spi_prepare / spi_execp spi_prepare / spi_exec_prepared
row iteration (-array/loop) spi_each(query, callable) added Streaming per-row callback, the inline-loop-body equivalent
streaming row-by-row (portal) spi_query / spi_fetchrow / spi_cursor_close added Constant-memory iteration over large result sets
catch with rich errorCode try/catch (PgError $e) added SQLSTATE via getSQLState(), plus detail and hint
quote quote_literal (+ quote_nullable, quote_ident)
elog level msg elog(level, msg) DEBUG/LOG/INFO/NOTICE/WARNING/ERROR
subtransaction { body } subtransaction(callable, …) added
commit / rollback spi_commit / spi_rollback
(no transform support) jsonb_plphp added TRANSFORM FOR TYPE jsonb; PL/Tcl has no transforms at all

The one remaining gap

  • Trusted / sandboxed language. PL/Tcl’s pltcl runs untrusted user code in a Safe-Tcl interpreter that restricts filesystem, network, and process access, so it is safe for non-superusers. Modern PHP has no comparable sandbox (safe_mode was removed in PHP 5.4), so PL/php is untrusted and superuser-only (see Security). This is the only PL/Tcl capability PL/php cannot practically match.

Notes on the additions

  • Event triggers dispatch through the same call handler; the function is declared RETURNS event_trigger and receives $_TD with event and tag.
  • Subtransactions roll back on a thrown PHP exception (which the caller can catch) or on a database error (which, under PL/php’s error model, aborts the statement). See Subtransactions.
  • Modules are loaded by wrapping each row’s source in a function and running it, so nested function/class declarations register globally for the session.
  • start_proc runs during the first PL/php call of a session.

See doc/plphp.md for full usage, and doc/plperl-comparison.md for the PL/Perl comparison.