33.7. Интерфейс быстрого пути
Postgres Pro предоставляет интерфейс для передачи серверу простых вызовов функций по быстрому пути.
Подсказка
Этот интерфейс несколько устарел, поскольку можно достичь подобной производительности и большей функциональности путём создания подготовленного оператора, определяющего вызов функции. Последующее выполнение этого оператора с передачей параметров и результатов в двоичном виде можно считать заменой вызову по быстрому пути.
Функция PQfn
запрашивает выполнение серверной функции посредством интерфейса быстрого доступа:
PGresult *PQfn(PGconn *conn, int fnid, int *result_buf, int *result_len, int result_is_int, const PQArgBlock *args, int nargs); typedef struct { int len; int isint; union { int *ptr; int integer; } u; } PQArgBlock;
Аргумент fnid
представляет собой OID функции, которая подлежит выполнению. args
и nargs
определяют параметры, которые должны быть переданы этой функции; они должны соответствовать списку аргументов объявленной функции. Когда поле isint
структуры, передаваемой в качестве параметра, имеет значение true, тогда значение u.integer
передаётся серверу в виде целого числа указанной длины (это должно быть 2 или 4 байта); при этом устанавливается нужный порядок байтов. Когда isint
имеет значение false, тогда указанное число байт по адресу *u.ptr
отправляется без какой-либо обработки; данные должны быть представлены в формате, которого ожидает сервер для передачи в двоичном виде данных того типа, что и аргументы функции. (Объявление поля u.ptr
, как имеющего тип int *
, является историческим; было бы лучше рассматривать его как тип void *
.) result_buf
указывает на буфер, в который должно быть помещено возвращаемое значение функции. Вызывающий код должен выделить достаточное место для сохранения возвращаемого значения. (Это никак не проверяется!) Фактическая длина результирующего значения в байтах будет возвращена в переменной целого типа, на которую указывает result_len
. Если ожидается получение двух- или четырёхбайтового целочисленного результата, то присвойте параметру result_is_int
значение 1, в противном случае назначьте ему 0. Когда параметр result_is_int
равен 1, libpq переставляет байты в передаваемом значении, если это необходимо, так, чтобы оно было доставлено на клиентскую машину в виде правильного значения типа int
; обратите внимание, что по адресу *result_buf
доставляется четырёхбайтовое целое для любого допустимого размера результата. Когда result_is_int
равен 0, тогда строка байтов в двоичном формате, отправленная сервером, будет возвращена немодифицированной. (В этом случае лучше рассматривать result_buf
как имеющий тип void *
.)
PQfn
всегда возвращает действительный указатель на объект PGresult
со статусом PGRES_COMMAND_OK
при успешном выполнении функции или PGRES_FATAL_ERROR
, если произошла какая-то ошибка. Перед использованием результата нужно сначала проверить его статус. Вызывающая функция отвечает за освобождение памяти, занимаемой объектом PGresult
, когда он больше не нужен, с помощью PQclear
.
Чтобы передать функции аргумент NULL, запишите в поле len
этой структуры значение -1
; поля isint
и u
в этом случае не важны. (Но это работает только при подключении по протоколу 3.0 и новее.)
Если функция возвращает NULL, в *result_len
записывается -1
, а *result_buf
не изменяется. (Это работает только при подключении по протоколу 3.0 и новее; в протоколе 2.0 ни *result_len
, ни *result_buf
не изменяется.)
Обратите внимание, что при использовании этого интерфейса невозможно обработать множества значений в результате. Кроме того, функция должна быть обычной, а не агрегатной или оконной.
33.7. The Fast-Path Interface
Postgres Pro provides a fast-path interface to send simple function calls to the server.
Tip
This interface is somewhat obsolete, as one can achieve similar performance and greater functionality by setting up a prepared statement to define the function call. Then, executing the statement with binary transmission of parameters and results substitutes for a fast-path function call.
The function PQfn
requests execution of a server function via the fast-path interface:
PGresult *PQfn(PGconn *conn, int fnid, int *result_buf, int *result_len, int result_is_int, const PQArgBlock *args, int nargs); typedef struct { int len; int isint; union { int *ptr; int integer; } u; } PQArgBlock;
The fnid
argument is the OID of the function to be executed. args
and nargs
define the parameters to be passed to the function; they must match the declared function argument list. When the isint
field of a parameter structure is true, the u.integer
value is sent to the server as an integer of the indicated length (this must be 2 or 4 bytes); proper byte-swapping occurs. When isint
is false, the indicated number of bytes at *u.ptr
are sent with no processing; the data must be in the format expected by the server for binary transmission of the function's argument data type. (The declaration of u.ptr
as being of type int *
is historical; it would be better to consider it void *
.) result_buf
points to the buffer in which to place the function's return value. The caller must have allocated sufficient space to store the return value. (There is no check!) The actual result length in bytes will be returned in the integer pointed to by result_len
. If a 2- or 4-byte integer result is expected, set result_is_int
to 1, otherwise set it to 0. Setting result_is_int
to 1 causes libpq to byte-swap the value if necessary, so that it is delivered as a proper int
value for the client machine; note that a 4-byte integer is delivered into *result_buf
for either allowed result size. When result_is_int
is 0, the binary-format byte string sent by the server is returned unmodified. (In this case it's better to consider result_buf
as being of type void *
.)
PQfn
always returns a valid PGresult
pointer, with status PGRES_COMMAND_OK
for success or PGRES_FATAL_ERROR
if some problem was encountered. The result status should be checked before the result is used. The caller is responsible for freeing the PGresult
with PQclear
when it is no longer needed.
To pass a NULL argument to the function, set the len
field of that parameter structure to -1
; the isint
and u
fields are then irrelevant. (But this works only in protocol 3.0 and later connections.)
If the function returns NULL, *result_len
is set to -1
, and *result_buf
is not modified. (This works only in protocol 3.0 and later connections; in protocol 2.0, neither *result_len
nor *result_buf
are modified.)
Note that it is not possible to handle set-valued results when using this interface. Also, the function must be a plain function, not an aggregate or window function.