36.8. Интерфейс быстрого пути
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
в этом случае не важны.
Если функция возвращает NULL, в *result_len
записывается -1
, а *result_buf
не изменяется.
Обратите внимание, что при использовании этого интерфейса невозможно обработать множества значений в результате. Кроме того, функция должна быть обычной функцией, а не процедурой, агрегатной или оконной функцией.
6.2. Updating Data
The modification of data that is already in the database is referred to as updating. You can update individual rows, all the rows in a table, or a subset of all rows. Each column can be updated separately; the other columns are not affected.
To update existing rows, use the UPDATE command. This requires three pieces of information:
The name of the table and column to update
The new value of the column
Which row(s) to update
Recall from Chapter 5 that SQL does not, in general, provide a unique identifier for rows. Therefore it is not always possible to directly specify which row to update. Instead, you specify which conditions a row must meet in order to be updated. Only if you have a primary key in the table (independent of whether you declared it or not) can you reliably address individual rows by choosing a condition that matches the primary key. Graphical database access tools rely on this fact to allow you to update rows individually.
For example, this command updates all products that have a price of 5 to have a price of 10:
UPDATE products SET price = 10 WHERE price = 5;
This might cause zero, one, or many rows to be updated. It is not an error to attempt an update that does not match any rows.
Let's look at that command in detail. First is the key word UPDATE
followed by the table name. As usual, the table name can be schema-qualified, otherwise it is looked up in the path. Next is the key word SET
followed by the column name, an equal sign, and the new column value. The new column value can be any scalar expression, not just a constant. For example, if you want to raise the price of all products by 10% you could use:
UPDATE products SET price = price * 1.10;
As you see, the expression for the new value can refer to the existing value(s) in the row. We also left out the WHERE
clause. If it is omitted, it means that all rows in the table are updated. If it is present, only those rows that match the WHERE
condition are updated. Note that the equals sign in the SET
clause is an assignment while the one in the WHERE
clause is a comparison, but this does not create any ambiguity. Of course, the WHERE
condition does not have to be an equality test. Many other operators are available (see Chapter 9). But the expression needs to evaluate to a Boolean result.
You can update more than one column in an UPDATE
command by listing more than one assignment in the SET
clause. For example:
UPDATE mytable SET a = 5, b = 3, c = 1 WHERE a > 0;