41.5. Доступ к базе данных из PL/Tcl#
41.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_prepare
query
typelist
Подготавливает и сохраняет план запроса для последующего выполнения. Сохраненный план будет сохранен на протяжении всей текущей сессии.
Запрос может использовать параметры, то есть заполнители для значений, которые будут предоставлены при выполнении плана. В строке запроса обращайтесь к параметрам по символам
$1
...$
. Если запрос использует параметры, необходимо указать имена типов параметров в виде Tcl-списка. (Если параметры не используются, напишите пустой список дляn
typelist
).Возвращаемое значение от функции
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
, чтобы гарантировать, что маркеры$
будут переданы вn
spi_prepare
без изменений и не будут заменены подстановкой переменных Tcl.subtransaction
command
Tcl-скрипт, содержащийся в
command
, выполняется в пределах SQL-подтранзакции. Если скрипт возвращает ошибку, вся подтранзакция откатывается перед возвратом ошибки в окружающий Tcl-код. См. Раздел 41.9 для получения дополнительной информации и примера.quote
string
Удваивает все апострофы и обратные косые черты в данной строке. Это может быть использовано для безопасного экранирования строк, которые будут вставлены в 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
level
msg
Выдает сообщение журнала или ошибки. Возможные уровни:
DEBUG
,LOG
,INFO
,NOTICE
,WARNING
,ERROR
иFATAL
. УровеньERROR
вызывает ошибочное состояние; если это не обрабатывается окружающим Tcl-кодом, ошибка передается вызывающему запросу, что приводит к прерыванию текущей транзакции или подтранзакции. Это фактически то же самое, что и команда Tclerror
. УровеньFATAL
прерывает транзакцию и приводит к завершению текущей сессии. (Вероятно, нет хорошей причины использовать этот уровень ошибки в функциях PL/Tcl, но он предоставляется для полноты). Другие уровни только генерируют сообщения разных приоритетов. Что касается сообщений определенного приоритета, то их отображение клиенту, запись в журнал сервера или оба действия контролируются переменными конфигурации log_min_messages и client_min_messages. Дополнительную информацию см. в разделах Глава 18 и Раздел 41.8.