42.4. Global Data in PL/Tcl
Sometimes it is useful to have some global data that is held between two calls to a function or is shared between different functions. This is easily done in PL/Tcl, but there are some restrictions that must be understood.
For security reasons, PL/Tcl executes functions called by any one SQL
role in a separate Tcl interpreter for that role. This prevents
accidental or malicious interference by one user with the behavior of
another user's PL/Tcl functions. Each such interpreter will have its own
values for any
"
global
"
Tcl variables. Thus, two PL/Tcl
functions will share the same global variables if and only if they are
executed by the same SQL role. In an application wherein a single
session executes code under multiple SQL roles (via
SECURITY
DEFINER
functions, use of
SET ROLE
, etc.) you may need to
take explicit steps to ensure that PL/Tcl functions can share data. To
do that, make sure that functions that should communicate are owned by
the same user, and mark them
SECURITY DEFINER
. You must of
course take care that such functions can't be used to do anything
unintended.
All PL/TclU functions used in a session execute in the same Tcl interpreter, which of course is distinct from the interpreter(s) used for PL/Tcl functions. So global data is automatically shared between PL/TclU functions. This is not considered a security risk because all PL/TclU functions execute at the same trust level, namely that of a database superuser.
To help protect PL/Tcl functions from unintentionally interfering
with each other, a global
array is made available to each function via the
upvar
command. The global name of this variable is the function's internal
name, and the local name is
GD
. It is recommended that
GD
be used
for persistent private data of a function. Use regular Tcl global
variables only for values that you specifically intend to be shared among
multiple functions. (Note that the
GD
arrays are only
global within a particular interpreter, so they do not bypass the
security restrictions mentioned above.)
An example of using
GD
appears in the
spi_execp
example below.