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