42.5. Обращение к базе данных из PL/Tcl
В этом разделе для обозначения необязательных элементов в описании синтаксиса используются знаки вопроса (а не квадратные скобки), как это принято в Tcl. Имеются следующие команды для доступа к базе данных из тела функции PL/Tcl:
- spi_exec?-count- n? ?-array- имя?- команда?- тело-цикла?
- Выполняет команду SQL, заданную в виде строки. В случае ошибки в этой команде выдаётся ошибка в Tcl. В противном случае - spi_execвозвращает число обработанных командой строк (выбранных, добавленных, изменённых или удалённых), либо ноль, если эта команда — служебный оператор. Кроме того, если команда — оператор- SELECT, значения выбранных столбцов помещаются в переменные Tcl, как описано ниже.- Необязательный аргумент - -countуказывает функции- spi_execостановиться после получения- nстрок, как если бы запрос включал предложение- LIMIT. Если- nравно нулю, запрос выполняется до конца, так же, как без указания- -count.- Если в качестве команды выполняется оператор - SELECT, значения результирующих столбцов помещаются в переменные Tcl, названные по именам столбцов. Если передаётся- -array, значения столбцов вместо этого становятся элементами названного ассоциативного массива, индексами в котором становятся имена столбцов. Кроме того, в элементе с именем «- .tupno» сохраняется номер текущей строки в результирующем наборе (отсчитывая от нуля), если только это имя не занято одним из столбцов результата.- Если в качестве команды выполняется - SELECTбез указания скрипта- тело-цикла, в переменных Tcl или элементах массива сохраняется только первая строка результатов; оставшиеся строки (если они есть), игнорируются. Если запрос не возвращает строки, не сохраняется ничего. (Этот случай можно отследить, проверив результат- spi_exec.) Например, команда:- spi_exec "SELECT count(*) AS cnt FROM pg_proc" - присвоит переменной - $cntв Tcl число строк, содержащихся в системном каталоге- pg_proc.- Если передаётся необязательный аргумент - тело-цикла, заданный в нём блок скрипта Tcl будет выполняться для каждой строки результата запроса. (Аргумент- тело-циклаигнорируется, если целевая команда — не- SELECT.) При этом значения столбцов текущей строки сохраняются в переменных Tcl или элементах массива перед каждой итерацией этого цикла. Например, код:- spi_exec -array C "SELECT * FROM pg_class" { elog DEBUG "have table $C(relname)" }- будет выводить в журнал сообщение для каждой строки - pg_class. Это работает подобно другим конструкциям циклов в Tcl; в частности, команды- continueи- breakв теле цикла будут действовать обычным образом.- Если в столбце результата запроса выдаётся NULL, целевая переменная для неё не устанавливается, и оказывается «неустановленной». 
- spi_prepare- query- список-типов
- Подготавливает и сохраняет план запроса для последующего выполнения. Сохранённый план будет продолжать существование до завершения текущего сеанса. - Запрос может принимать параметры, то есть местозаполнители для значений, которые будут передаваться, когда план будет собственно выполняться. В строке запроса эти параметры обозначаются как - $1...- $. Если в запросе используются параметры, нужно задать имена типов этих параметров в виде списка Tcl. (Если параметры отсутствуют, задайте пустой- n- список_типов.)- Функция - spi_prepareвозвращает идентификатор запроса, который может использоваться в последующих вызовах- spi_execp. Пример приведён в описании- spi_execp.
- spi_execp?-count- n? ?-array- имя? ?-nulls- строка?- ид-запроса?- список-значений? ?- тело-цикла?
- Выполняет запрос, ранее подготовленный функцией - spi_prepare. В качестве- ид_запросапередаётся идентификатор, возвращённый функцией- spi_prepare. Если в запросе задействуются параметры, необходимо указать- список-значений. Это должен быть принятый в Tcl список параметров. Он должен иметь ту же длину, что и список типов параметров, ранее переданный- spi_prepare. Опустите- список-значений, если у запроса нет параметров.- Необязательный аргумент - -nullsпринимает строку из пробелов и символов- 'n', которые отмечают, в каких параметрах- spi_execpпередаются значения NULL. Если присутствует, эта строка должна иметь ту же длину, что и- список-значений. В случае её отсутствия значения всех параметров считаются отличными от NULL.- Не считая отличий в способе передачи запроса и параметров, - spi_execpработает так же, как- spi_exec. Параметры- -count,- -arrayи- тело-циклазадаются так же, и так же передаётся возвращаемое значение.- Взгляните на пример функции на PL/Tcl, использующей подготовленный план: - CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS $$ if {![ info exists GD(plan) ]} { # подготовить сохранённый план при первом вызове set GD(plan) [ spi_prepare \ "SELECT count(*) AS cnt FROM t1 WHERE num >= \$1 AND num <= \$2" \ [ list int4 int4 ] ] } spi_execp -count 1 $GD(plan) [ list $1 $2 ] return $cnt $$ LANGUAGE pltcl;- Обратные косые черты внутри строки запроса, передаваемой функции - spi_prepare, нужны для того, чтобы маркеры- $передавались функции- n- spi_prepareкак есть, а не заменялись при подстановке переменных Tcl.
- subtransaction- команда
- Скрипт Tcl, который содержит - команда, выполняется в подтранзакции SQL. Если этот скрипт возвращает ошибку, вся подтранзакция откатывается назад, а затем в окружающий код Tcl возвращается ошибка. За дополнительными подробностями и примером обратитесь к Разделу 42.9.
- quote- строка
- Дублирует все вхождения апострофа и обратной косой черты в заданной строке. Это можно использовать для защиты строк, которые будут вставляться в команды SQL, передаваемые в - spi_execили- spi_prepare. Например, представьте, что при выполнении такой команды SQL:- "SELECT '$val' AS ret" - переменная языка Tcl - valсодержит- doesn't. Это приведёт к формированию такой окончательной строки команды:- SELECT 'doesn't' AS ret - при разборе которой в процессе - spi_execили- spi_prepareвозникнет ошибка. Чтобы этот запрос работал правильно, итоговая команда должна выглядеть так:- SELECT 'doesn''t' AS ret - Получить её в PL/Tcl можно так: - "SELECT '[ quote $val ]' AS ret" - Преимуществом - spi_execpявляется то, что для неё заключать значения параметров в кавычки подобным образом не нужно, так как параметры никогда не разбираются в составе строки команды SQL.
-  elogуровеньсообщение
- Выдаёт служебное сообщение или сообщение об ошибке. Возможные уровни сообщений: - DEBUG(ОТЛАДКА),- LOG(СООБЩЕНИЕ),- INFO(ИНФОРМАЦИЯ),- NOTICE(ЗАМЕЧАНИЕ),- WARNING(ПРЕДУПРЕЖДЕНИЕ),- ERROR(ОШИБКА) и- FATAL(ВАЖНО). С уровнем- ERRORвыдаётся ошибка; если она не перехватывается окружающим кодом Tcl, она распространяется в вызывающий запрос, что приводит к прерыванию текущей транзакции или подтранзакции. По сути то же самое делает команда- errorязыка Tcl. Сообщение уровня- FATALпрерывает транзакцию и приводит к завершению текущего сеанса. (Вероятно, нет обоснованной причины использовать этот уровень ошибок в функциях PL/Tcl, но он поддерживается для полноты.) При использовании других уровней происходит просто вывод сообщения с заданным уровнем важности. Будут ли сообщения определённого уровня передаваться клиенту и/или записываться в журнал, определяется конфигурационными переменными log_min_messages и client_min_messages. За дополнительными сведениями обратитесь к Главе 18 и Разделу 42.8.