有时候需要在同一个函数的两次调用间保持某些全局数据或者在不同的函数之间共享全局数据。在 PL/Tcl 中这很容易做到,但是必须了解一些限制。
出于安全原因,PL/Tcl为每个SQL角色调用的函数在一个单独的Tcl解释器中执行。
这可以防止一个用户意外或恶意干扰另一个用户的PL/Tcl函数行为。
每个这样的解释器将有自己的值用于任何“global”的Tcl变量。
因此,只有当它们由相同的SQL角色执行时,两个PL/Tcl函数才会共享相同的全局变量。
在一个应用程序中,一个会话通过SECURITY DEFINER
函数、使用SET ROLE
等方式执行多个SQL角色的代码时,
您可能需要采取明确步骤来确保PL/Tcl函数可以共享数据。
为此,请确保应该通信的函数由同一用户拥有,并标记为SECURITY DEFINER
。
当然,您必须小心,这些函数不能被用于执行任何意外操作。
在一个会话中使用的所有 PL/TclU 函数都在同一个 Tcl 解释器中执行,这当然与用于 PL/Tcl 函数的解释器不同。因此,在 PL/TclU 函数之间会自动地共享全局数据。这并不是一种安全性风险,因为所有的 PL/TclU 函数都在同样的信任级别上执行,即都以数据库超级用户的级别执行。
为了保护 PL/Tcl 函数不会无意间彼此干扰,通过upvar
命令可以建立一个对每个函数可用的全局数组。这个变量的全局名称是该函数的内部名称,并且本地名称为GD
。推荐使用GD
来保持一个函数的持久私有数据。只对你特别希望在多个函数之间共享的值使用常规的 Tcl 全局变量(注意GD
数组只在一个特定的解释器中是全局的,因此它们不会绕过上文提到的安全性限制)。
下文的spi_execp
例子中有一个使用GD
的例子。