32.6. Извлечение порциями информации, связанной с результатом запроса #
Обычно libpq собирает весь результат выполнения SQL-команды и возвращает его приложению в виде единственной структуры PGresult
. Это может оказаться неприемлемым для команд, которые возвращают большое число строк. В таких случаях приложение может воспользоваться функциями PQsendQuery
и PQgetResult
в однострочном режиме или порционном режиме. В этих режимах результирующие строки передаются приложению по мере того, как они принимаются от сервера, — по одной за раз в однострочном и по несколько в порционном режиме.
Для того чтобы войти в один из этих режимов, вызовите PQsetSingleRowMode
или PQsetChunkedRowsMode
сразу же после успешного вызова функции PQsendQuery
(или родственной функции). Выбор этого режима действителен только для запроса, исполняемого в данный момент. Затем повторно вызывайте функцию PQgetResult
до тех пор, пока она не возвратит null, как описано в Раздел 32.4. Если запрос возвращает какое-то число строк, то они возвращаются в виде одного или нескольких объектов PGresult
, которые выглядят, как обычные выборки, за исключением того, что их код статуса будет PGRES_SINGLE_TUPLE
в однострочном режиме или PGRES_TUPLES_CHUNK
в порционном режиме вместо PGRES_TUPLES_OK
. В каждом объекте PGRES_SINGLE_TUPLE
будет выведена только одна результирующая строка, в то время как объект PGRES_TUPLES_CHUNK
содержит хотя бы одну строку, но не больше указанного числа строк на одну порцию. После последней строки (или сразу же, если запрос не возвращает ни одной строки) будет возвращён объект, не содержащий ни одной строки и имеющий статус PGRES_TUPLES_OK
; это сигнал о том, что строк больше не будет. (Но обратите внимание, что всё же необходимо продолжать вызывать функцию PQgetResult
, пока она не возвратит null.) Все эти объекты PGresult
будут содержать те же самые описательные данные (имена столбцов, типы и т. д.), которые имел бы обычный объект PGresult
. Память, занимаемую каждым объектом, нужно освобождать с помощью PQclear
, как обычно.
При использовании конвейерного режима необходимо активировать однострочный или порционный режим для каждого запроса в конвейере, прежде чем получать результаты для этого запроса с помощью PQgetResult
. См. Раздел 32.5 для получения дополнительной информации.
PQsetSingleRowMode
#Выбирает однострочный режим для текущего выполняющегося запроса.
int PQsetSingleRowMode(PGconn *conn);
Эту функцию можно вызывать только непосредственно после функции
PQsendQuery
или одной из её родственных функций, до выполнения любой другой операции через это подключение, такой, какPQconsumeInput
илиPQgetResult
. Если вызвать её в подходящий момент, функция активирует однострочный режим для текущего запроса и возвращает 1. В противном случае режим остаётся прежним, а функция возвращает 0. Режим в любом случае сбрасывается по завершении текущего запроса.PQsetChunkedRowsMode
#Выбирает порционный режим для текущего выполняющегося запроса.
int PQsetChunkedRowsMode(PGconn *conn, int chunkSize);
Эта функция похожа на
PQsetSingleRowMode
, но вместо того, чтобы получать на каждыйPGresult
только одну строку за раз, выводит порции строк, максимальное количество которых указано вchunkSize
. Данную функцию можно вызывать только сразу после функцииPQsendQuery
или одной из её родственных функций, до выполнения любой другой операции через это подключение, такой, какPQconsumeInput
илиPQgetResult
. Если вызвать её в подходящий момент, функция активирует порционный режим для текущего запроса и возвращает 1. В противном случае режим остаётся прежним, а функция возвращает 0. Режим в любом случае сбрасывается по завершении текущего запроса.
Внимание
В процессе обработки запроса сервер может возвратить некоторое количество строк, а затем столкнуться с ошибкой, вынуждающей его аварийно завершить запрос. Обычно libpq отбрасывает такие строки и сообщает только об ошибке. Но в однострочном или порционном режиме эти строки уже будут возвращены приложению. Следовательно, приложение увидит ряд объектов PGresult
, имеющих статус PGRES_SINGLE_TUPLE
или PGRES_TUPLES_CHUNK
, за которыми последует объект со статусом PGRES_FATAL_ERROR
. Для обеспечения надлежащего поведения транзакций приложение должно быть спроектировано таким образом, чтобы отбрасывать или отменять все операции, проведённые с уже обработанными строками, если запрос в конечном итоге завершается сбоем.