Postgresql 中文操作指南

44.4. Global Data in 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 数组仅是特定解释器内部的全局变量,因此它们不会绕过上述安全限制。)

GD 使用示例描述见下面的 spi_execp 示例。