42.5. Доступ к базе данных из PL/Tcl#
42.5. Доступ к базе данных из PL/Tcl #
В этом разделе мы следуем обычной традиции Tcl и используем вопросительные знаки, а не скобки, для обозначения необязательного элемента в синтаксическом обзоре. Следующие команды доступны для доступа к базе данных из тела функции PL/Tcl:
spi_exec?-countn? ?-arrayname?command?loop-body?Выполняет SQL-команду, заданную в виде строки. Ошибка в команде вызывает ошибку. В противном случае, возвращаемое значение функции
spi_exec- это количество обработанных строк (выбранных, вставленных, обновленных или удаленных) командой, или ноль, если команда является утилитарным оператором. Кроме того, если команда является операторомSELECT, значения выбранных столбцов помещаются в переменные Tcl, как описано ниже.Опциональное значение
-countуказываетspi_execостановиться после того, как будут полученыnстрок, как если бы в запросе было указано предложениеLIMIT. Еслиnравно нулю, запрос выполняется до завершения, так же, как когда-countпрне указан.Если команда является оператором
SELECT, значения столбцов результата помещаются в переменные Tcl с именами, соответствующими именам столбцов. Если указана опция-array, значения столбцов вместо этого сохраняются в элементах именованного ассоциативного массива, где имена столбцов используются в качестве индексов массива. Кроме того, текущий номер строки в результате (считая с нуля) сохраняется в элементе массива с именем “.tupno”, если это имя не используется в качестве имени столбца в результате.Если команда является оператором
SELECTи не задан скриптloop-body, тогда только первая строка результатов сохраняется в переменные Tcl или элементы массива; остальные строки, если они есть, игнорируются. Если запрос не возвращает ни одной строки, то сохранение не происходит. (Этот случай можно обнаружить, проверив результатspi_exec). Например:spi_exec "SELECT count(*) AS cnt FROM pg_proc"
установит переменную Tcl
$cntв количество строк в системном каталогеpg_proc.Если задан необязательный аргумент
loop-body, то это фрагмент скрипта Tcl, который выполняется один раз для каждой строки в результате запроса. (loop-bodyигнорируется, если заданная команда не являетсяSELECT). Значения столбцов текущей строки сохраняются в переменных или элементах массива Tcl перед каждой итерацией. Например:spi_exec -array C "SELECT * FROM pg_class" { elog DEBUG "have table $C(relname)" }будет выводить сообщение журнала для каждой строки
pg_class. Эта функция работает аналогично другим циклическим конструкциям Tcl; в частности,continueиbreakработают обычным образом внутри тела цикла.Если столбец результата запроса является пустым, целевая переменная для него будет “неустановленной”, а не установленной.
spi_preparequerytypelistПодготавливает и сохраняет план запроса для последующего выполнения. Сохраненный план будет сохранен на протяжении всей текущей сессии.
Запрос может использовать параметры, то есть заполнители для значений, которые будут предоставлены при выполнении плана. В строке запроса обращайтесь к параметрам по символам
$1...$. Если запрос использует параметры, необходимо указать имена типов параметров в виде Tcl-списка. (Если параметры не используются, напишите пустой список дляntypelist).Возвращаемое значение от функции
spi_prepareявляется идентификатором запроса, который будет использоваться в последующих вызовах функцииspi_execp. См. пример в функцииspi_execp.spi_execp?-countn? ?-arrayname? ?-nullsstring?queryid?value-list? ?loop-body?Выполняет запрос, ранее подготовленный с помощью функции
spi_prepare.queryid- это идентификатор, возвращаемый функциейspi_prepare. Если запрос ссылается на параметры, необходимо предоставитьvalue-list. Это список фактических значений для параметров в формате Tcl. Список должен иметь такую же длину, как и список типов параметров, предоставленный ранее функцииspi_prepare. Оставьтеvalue-listпустым, если запрос не содержит параметров.Опциональное значение для
-nullsпредставляет собой строку из пробелов и символов'n', которая сообщает функцииspi_execp, какие из параметров являются пустыми значениями. Если значение задано, оно должно иметь точно такую же длину, как иvalue-list. Если значение не задано, все значения параметров являются ненулевыми.За исключением способа указания запроса и его параметров, функция
spi_execpработает так же, как функцияspi_exec. Опции-count,-arrayиloop-bodyаналогичны, а также значение результата.Вот пример функции PL/Tcl, использующей подготовленный план:
CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS $$ if {![ info exists GD(plan) ]} { # prepare the saved plan on the first call 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, чтобы гарантировать, что маркеры$будут переданы вnspi_prepareбез изменений и не будут заменены подстановкой переменных Tcl.subtransactioncommandTcl-скрипт, содержащийся в
command, выполняется в пределах SQL-подтранзакции. Если скрипт возвращает ошибку, вся подтранзакция откатывается перед возвратом ошибки в окружающий Tcl-код. См. Раздел 42.9 для получения дополнительной информации и примера.quotestringУдваивает все апострофы и обратные косые черты в данной строке. Это может быть использовано для безопасного экранирования строк, которые будут вставлены в 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.-
eloglevelmsg Выдает сообщение журнала или ошибки. Возможные уровни:
DEBUG,LOG,INFO,NOTICE,WARNING,ERRORиFATAL. УровеньERRORвызывает ошибочное состояние; если это не обрабатывается окружающим Tcl-кодом, ошибка передается вызывающему запросу, что приводит к прерыванию текущей транзакции или подтранзакции. Это фактически то же самое, что и команда Tclerror. УровеньFATALпрерывает транзакцию и приводит к завершению текущей сессии. (Вероятно, нет хорошей причины использовать этот уровень ошибки в функциях PL/Tcl, но он предоставляется для полноты). Другие уровни только генерируют сообщения разных приоритетов. Что касается сообщений определенного приоритета, то их отображение клиенту, запись в журнал сервера или оба действия контролируются переменными конфигурации log_min_messages и client_min_messages. Дополнительную информацию см. в разделах Глава 19 и Раздел 42.8.