41.4. Глобальные данные в PL/Tcl#
41.4. Глобальные данные в 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
ниже.