34.3. Функции для исполнения команд #
После того как соединение с сервером было успешно установлено, функции, описанные в этом разделе, используются для выполнения SQL-запросов и команд.
34.3.1. Главные функции #
PQexec
#Передаёт команду серверу и ожидает результата.
PGresult *PQexec(PGconn *conn, const char *command);
Возвращает указатель на
PGresult
или, возможно, пустой указатель (null). Как правило, возвращается непустой указатель, исключением являются ситуации нехватки памяти или серьёзные ошибки, такие, как невозможность отправки команды серверу. Для проверки возвращаемого значения на наличие ошибок следует вызвать функциюPQresultStatus
(в случае нулевого указателя она возвратитPGRES_FATAL_ERROR
). Для получения дополнительной информации о таких ошибках используйте функциюPQerrorMessage
.
Строка команды может включать в себя более одной SQL-команды (которые разделяются точкой с запятой). Несколько запросов, отправленных с помощью одного вызова PQexec
, обрабатываются в рамках одной транзакции, если только команды BEGIN
/COMMIT
не включены явно в строку запроса, чтобы разделить его на несколько транзакций. (Подробнее о том, как сервер обрабатывает строки, включающие несколько команд, рассказывается в Подразделе 55.2.2.1.) Однако обратите внимание, что возвращаемая структура PGresult
описывает только результат последней из выполненных команд, содержащихся в строке запроса. Если одна из команд завершается сбоем, то обработка строки запроса на этом останавливается, и возвращённая структура PGresult
описывает состояние ошибки.
PQexecParams
#Отправляет команду серверу и ожидает результата. Имеет возможность передать параметры отдельно от текста SQL-команды.
PGresult *PQexecParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
PQexecParams
подобнаPQexec
, но предлагает дополнительную функциональность: значения параметров могут быть указаны отдельно от самой строки-команды, а результаты запроса могут быть затребованы либо в текстовом, либо в двоичном формате.Параметры функции следующие:
conn
Объект, описывающий подключение, через которое пересылается команда.
command
Строка SQL-команды, которая должна быть выполнена. Если используются параметры, то в строке команды на них ссылаются, как
$1
,$2
и т. д.nParams
Число предоставляемых параметров. Оно равно длине массивов
paramTypes[]
,paramValues[]
,paramLengths[]
иparamFormats[]
. (Указатели на массивы могут быть равныNULL
, когдаnParams
равно нулю.)paramTypes[]
Предписывает, посредством OID, типы данных, которые должны быть назначены параметрам. Если значение
paramTypes
равноNULL
или какой-либо отдельный элемент в массиве равен нулю, тогда сервер самостоятельно определит тип данных для параметра точно таким же образом, как он сделал бы для литеральной строки, тип которой не указан.paramValues[]
Указывает фактические значения параметров. Нулевой указатель в этом массиве означает, что соответствующий параметр равен null; в противном случае указатель указывает на текстовую строку, завершающуюся нулевым символом (для текстового формата), или на двоичные данные в формате, которого ожидает сервер (для двоичного формата).
paramLengths[]
Указывает фактические длины данных для параметров, представленных в двоичном формате. Он игнорируется для параметров, имеющих значение null, и для параметров, представленных в текстовом формате. Указатель на массив может быть нулевым, когда нет двоичных параметров.
paramFormats[]
Указывает, являются ли параметры текстовыми (поместите нуль в элемент массива, соответствующий такому параметру) или двоичными (поместите единицу в элемент массива, соответствующий такому параметру). Если указатель на массив является нулевым, тогда все параметры считаются текстовыми строками.
Значения, переданные в двоичном формате, требуют знания внутреннего представления, которого ожидает сервер. Например, целые числа должны передаваться с использованием сетевого порядка байтов. Передача значений типа
numeric
требует знания формата, в котором их хранит сервер.resultFormat
Требует указать ноль, чтобы получить результаты в текстовом формате, или единицу, чтобы получить результаты в двоичном формате. (В настоящее время нет возможности получить различные столбцы результата в разных форматах, хотя это и возможно на уровне протокола, лежащего в основе подключений.)
Главным преимуществом PQexecParams
перед PQexec
является возможность отделить значения параметров от строки запроса. Это позволяет обойтись без кавычек и экранирующих символов, манипулирование которыми бывает трудоёмким и часто приводит к ошибкам.
В отличие от PQexec
, PQexecParams
позволяет включать не более одной SQL-команды в строку запроса. (В ней могут содержаться точки с запятой, однако может присутствовать не более одной непустой команды.) Это ограничение накладывается базовым протоколом, но оно приносит и некоторую пользу в качестве дополнительной защиты от атак методом SQL-инъекций.
Подсказка
Указание типов параметров с помощью OID является трудоёмким, особенно если вы предпочитаете не указывать явно значений OID в вашей программе. Однако вы можете избежать этого даже в случаях, когда сервер самостоятельно не может определить тип параметра или выбирает не тот тип, который вы хотите. В строке SQL-команды добавьте явное приведение типа для этого параметра, чтобы показать, какой тип данных вы будете отправлять. Например:
SELECT * FROM mytable WHERE x = $1::bigint;
Это приведёт к тому, что параметр $1
будет считаться имеющим тип bigint
, в то время как по умолчанию ему был бы назначен тот же самый тип, что и x
. Такое явное принятие решения о типе параметра либо с помощью описанного метода, либо путём задания числового OID строго рекомендуется, когда значения параметров отправляются в двоичном формате, поскольку двоичный формат имеет меньшую избыточность, чем текстовый, и поэтому гораздо менее вероятно, что сервер обнаружит ошибку несоответствия типов, допущенную вами.
PQprepare
#Отправляет запрос, чтобы создать подготовленный оператор с конкретными параметрами, и ожидает завершения.
PGresult *PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes);
PQprepare
создаёт подготовленный оператор для последующего исполнения с помощьюPQexecPrepared
. Благодаря этому, команды, которые будут выполняться многократно, не потребуется разбирать и планировать каждый раз; за подробностями обратитесь к PREPARE.Функция создаёт подготовленный оператор с именем
stmtName
из строкиquery
, которая должна содержать единственную SQL-команду.stmtName
может быть пустой строкой""
, тогда будет создан неименованный оператор (в таком случае любой уже существующий неименованный оператор будет автоматически заменён), в противном случае, если имя оператора уже определено в текущем сеансе работы, будет ошибка. Если используются параметры, то в запросе к ним обращаются таким образом:$1
,$2
и т. д.nParams
представляет число параметров, типы данных для которых указаны в массивеparamTypes[]
. (Указатель на массив может быть равенNULL
, когда значениеnParams
равно нулю.)paramTypes[]
указывает, посредством OID, типы данных, которые будут назначены параметрам. ЕслиparamTypes
равенNULL
или какой-либо элемент в этом массиве равен нулю, то сервер назначает тип данных соответствующему параметру точно таким же способом, как он сделал бы для литеральной строки, не имеющей типа. Также в запросе можно использовать параметры с номерами, большими, чемnParams
; типы данных для них сервер также сможет подобрать. (См. описаниеPQdescribePrepared
, где сказано, как можно определить, какие типы данных были подобраны).Как и при вызове
PQexec
, результатом является объектPGresult
, содержимое которого показывает успех или сбой на стороне сервера. Нулевой указатель означает нехватку памяти или невозможность вообще отправить команду. Для получения дополнительной информации о таких ошибках используйтеPQerrorMessage
.
Подготовленные операторы для использования с PQexecPrepared
можно также создать путём исполнения SQL-команд PREPARE.
PQexecPrepared
#Отправляет запрос на исполнение подготовленного оператора с данными параметрами и ожидает результата.
PGresult *PQexecPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
PQexecPrepared
подобнаPQexecParams
, но команда, подлежащая исполнению, указывается путём передачи имени предварительно подготовленного оператора вместо передачи строки запроса. Эта возможность позволяет командам, которые вызываются многократно, подвергаться разбору и планированию только один раз, а не при каждом их исполнении. Оператор должен быть подготовлен предварительно в рамках текущего сеанса работы.Параметры идентичны
PQexecParams
, за исключением того, что вместо строки запроса передаётся имя подготовленного оператора и отсутствует параметрparamTypes[]
(он не нужен, поскольку типы данных для параметров подготовленного оператора были определены при его создании).PQdescribePrepared
#Передаёт запрос на получение информации об указанном подготовленном операторе и ожидает завершения.
PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName);
PQdescribePrepared
позволяет приложению получить информацию о предварительно подготовленном операторе.Для ссылки на неименованный оператор значение
stmtName
может быть пустой строкой""
илиNULL
, в противном случае оно должно быть именем существующего подготовленного оператора. В случае успешного выполнения возвращаетсяPGresult
со статусомPGRES_COMMAND_OK
. ФункцииPQnparams
иPQparamtype
позволяют извлечь изPGresult
информацию о параметрах подготовленного оператора, а функцииPQnfields
,PQfname
,PQftype
и т. п. предоставляют информацию о результирующих столбцах данного оператора (если они есть).PQdescribePortal
#Передаёт запрос на получение информации об указанном портале и ожидает завершения.
PGresult *PQdescribePortal(PGconn *conn, const char *portalName);
PQdescribePortal
позволяет приложению получить информацию о предварительно созданном портале. (libpq не предоставляет прямого доступа к порталам, но вы можете использовать эту функцию для ознакомления со свойствами курсора, созданного с помощью SQL-командыDECLARE CURSOR
.)Для ссылки на неименованный портал значение
portalName
может быть пустой строкой""
илиNULL
, в противном случае оно должно быть именем существующего портала. В случае успешного завершения возвращаетсяPGresult
со статусомPGRES_COMMAND_OK
. С помощью функцийPQnfields
,PQfname
,PQftype
и т. д. можно извлечь изPGresult
информацию о результирующих столбцах данного портала (если они есть).PQclosePrepared
#Передаёт запрос на закрытие указанного подготовленного оператора и ожидает завершения.
PGresult *PQclosePrepared(PGconn *conn, const char *stmtName);
PQclosePrepared
позволяет приложению закрыть ранее подготовленный оператор. Закрытие оператора высвобождает все задействованные им ресурсы на сервере, а также позволяет переиспользовать его имя.Для ссылки на безымянный оператор значение
stmtName
может быть пустой строкой""
илиNULL
. Если имя совпадает с именем существующего оператора, команда ничего не делает. В случае успешного завершения возвращаетсяPGresult
со статусомPGRES_COMMAND_OK
.PQclosePortal
#Передаёт запрос на закрытие указанного портала и ожидает завершения.
PGresult *PQclosePortal(PGconn *conn, const char *portalName);
PQclosePortal
позволяет приложению закрыть ранее созданный портал. Закрытие портала высвобождает все задействованные им ресурсы на сервере, а также позволяет переиспользовать его имя. (libpq не предоставляет прямого доступа к порталам, но вы можете использовать эту функцию, чтобы закрыть курсор, созданный с помощью SQL-командыDECLARE CURSOR
.)Для ссылки на безымянный портал значение
portalName
может быть пустой строкой""
илиNULL
. Если имя совпадает с именем существующего портала, команда ничего не делает. В случае успешного завершения возвращаетсяPGresult
со статусомPGRES_COMMAND_OK
.
Структура PGresult
содержит результат, возвращённый сервером. Разработчики приложений libpq должны тщательно поддерживать абстракцию PGresult
. Для получения доступа к содержимому PGresult
используйте функции доступа, описанные ниже. Избегайте непосредственного обращения к полям структуры PGresult
, поскольку они могут измениться в будущем.
PQresultStatus
#Возвращает статус результата выполнения команды.
ExecStatusType PQresultStatus(const PGresult *res);
PQresultStatus
может возвращать одно из следующих значений:PGRES_EMPTY_QUERY
#Строка, отправленная серверу, была пустой.
PGRES_COMMAND_OK
#Успешное завершение команды, не возвращающей никаких данных.
PGRES_TUPLES_OK
#Успешное завершение команды, возвращающей данные (такой, как
SELECT
илиSHOW
).PGRES_COPY_OUT
#Начат перенос данных Copy Out (с сервера).
PGRES_COPY_IN
#Начат перенос данных Copy In (на сервер).
PGRES_BAD_RESPONSE
#Ответ сервера не был распознан.
PGRES_NONFATAL_ERROR
#Произошла некритическая ошибка (уведомление или предупреждение).
PGRES_FATAL_ERROR
#Произошла критическая ошибка.
PGRES_COPY_BOTH
#Начат перенос данных Copy In/Out (на сервер и с сервера). Эта функция в настоящее время используется только для потоковой репликации, поэтому такой статус не должен иметь место в обычных приложениях.
PGRES_SINGLE_TUPLE
#Структура
PGresult
содержит только одну результирующую строку, возвращённую текущей командой. Этот статус имеет место только тогда, когда для данного запроса был выбран режим построчного вывода (см. Раздел 34.6).PGRES_TUPLES_CHUNK
#Структура
PGresult
содержит несколько результирующих кортежей, возвращённых текущей командой. Этот статус имеет место только тогда, когда для данного запроса был выбран режим построчного вывода (см. Раздел 34.6). Количество кортежей не превысит ограниченияPQsetChunkedRowsMode
.PGRES_PIPELINE_SYNC
#PGresult
представляет точку синхронизации в конвейерном режиме, запрошеннуюPQpipelineSync
илиPQsendPipelineSync
. Этот статус возможен, только если выбран конвейерный режим.PGRES_PIPELINE_ABORTED
#Структура
PGresult
представляет конвейер, получивший ошибку от сервера. ФункцияPQgetResult
должна вызываться неоднократно, и каждый раз она будет возвращать этот код состояния до конца текущего конвейера, после чего она вернётPGRES_PIPELINE_SYNC
и сможет возобновиться нормальная обработка.
Если статус результата
PGRES_TUPLES_OK
,PGRES_SINGLE_TUPLE
илиPGRES_TUPLES_CHUNK
, тогда для извлечения строк, возвращённых запросом, можно использовать функции, описанные ниже. Обратите внимание, что командаSELECT
, даже когда она не извлекает ни одной строки, всё же показываетPGRES_TUPLES_OK
.PGRES_COMMAND_OK
предназначен для команд, которые никогда не возвращают строки (INSERT
илиUPDATE
без использования предложенияRETURNING
и др.). ОтветPGRES_EMPTY_QUERY
может указывать на наличие ошибки в клиентском программном обеспечении.Результат со статусом
PGRES_NONFATAL_ERROR
никогда не будет возвращён напрямую функциейPQexec
или другими функциями исполнения запросов; вместо этого результаты такого вида передаются обработчику уведомлений (см. Раздел 34.13).PQresStatus
#Преобразует значение перечислимого типа, возвращённое функцией
PQresultStatus
, в строковую константу, описывающую код статуса. Вызывающая функция не должна освобождать память, на которую указывает возвращаемый указатель.char *PQresStatus(ExecStatusType status);
PQresultErrorMessage
#Возвращает сообщение об ошибке, связанное с командой, или пустую строку, если ошибки не произошло.
char *PQresultErrorMessage(const PGresult *res);
Если произошла ошибка, то возвращённая строка будет включать завершающий символ новой строки. Вызывающая функция не должна напрямую освобождать память, на которую указывает возвращаемый указатель. Она будет освобождена, когда соответствующий указатель
PGresult
будет передан функцииPQclear
.Если непосредственно после вызова
PQexec
илиPQgetResult
вызвать функциюPQerrorMessage
(для данного подключения), то она возвратит ту же самую строку, что иPQresultErrorMessage
(для данного результата). ОднакоPGresult
сохранит своё сообщение об ошибке до тех пор, пока не будет уничтожен, в то время как сообщение об ошибке, связанное с данным подключением, будет изменяться при выполнении последующих операций. Воспользуйтесь функциейPQresultErrorMessage
, когда вы хотите узнать статус, связанный с конкретной структуройPGresult
; используйте функциюPQerrorMessage
, когда вы хотите узнать статус выполнения самой последней операции на данном соединении.PQresultVerboseErrorMessage
#Возвращает переформатированную версию сообщения об ошибке, связанного с объектом
PGresult
.char *PQresultVerboseErrorMessage(const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context);
В некоторых ситуациях клиент может захотеть получить более подробную версию ранее выданного сообщения об ошибке. Эту потребность удовлетворяет функция
PQresultVerboseErrorMessage
, формируя сообщение, которое было бы выдано функциейPQresultErrorMessage
, если бы заданный уровень детализации был текущим для соединения в момент заполненияPGresult
. Если же вPGresult
не содержится ошибка, вместо этого выдаётся сообщение «PGresult is not an error result» (PGresult — не результат с ошибкой). Возвращаемое этой функцией сообщение завершается переводом строки.В отличие от многих других функций, извлекающих данные из
PGresult
, результат этой функции — новая размещённая в памяти строка. Когда эта строка будет не нужна, вызывающий код должен освободить её место, вызвавPQfreemem()
.При нехватке памяти может быть возвращёно NULL.
PQresultErrorField
#Возвращает индивидуальное поле из отчёта об ошибке.
char *PQresultErrorField(const PGresult *res, int fieldcode);
fieldcode
это идентификатор поля ошибки; см. символические константы, перечисленные ниже. ЕслиPGresult
не содержит ошибки или предупреждения или не включает указанное поле, то возвращаетсяNULL
. Значения полей обычно не включают завершающий символ новой строки. Вызывающая функция не должна напрямую освобождать память, на которую указывает возвращаемый указатель. Она будет освобождена, когда соответствующий указательPGresult
будет передан функцииPQclear
.Доступны следующие коды полей:
PG_DIAG_SEVERITY
#Серьёзность; поле может содержать
ERROR
,FATAL
илиPANIC
(в сообщении об ошибке) либоWARNING
,NOTICE
,DEBUG
,INFO
илиLOG
(в сообщении-уведомлении) либо локализованный перевод одного из этих значений. Присутствует всегда.PG_DIAG_SEVERITY_NONLOCALIZED
#Серьёзность; поле может содержать
ERROR
,FATAL
илиPANIC
(в сообщении об ошибке) либоWARNING
,NOTICE
,DEBUG
,INFO
илиLOG
(в сообщении-уведомлении). Это поле подобноPG_DIAG_SEVERITY
, но его содержимое никогда не переводится. Присутствует только в отчётах, выдаваемых Postgres Pro версии 9.6 и новее.PG_DIAG_SQLSTATE
#Код ошибки в соответствии с соглашением о кодах SQLSTATE. Код SQLSTATE идентифицирует тип случившейся ошибки; он может использоваться клиентскими приложениями, чтобы выполнять конкретные операции (такие, как обработка ошибок) в ответ на конкретную ошибку базы данных. Список возможных кодов SQLSTATE приведён в Приложении A. Это поле не подлежит локализации. Оно всегда присутствует.
PG_DIAG_MESSAGE_PRIMARY
#Главное сообщение об ошибке, предназначенное для прочтения пользователем. Как правило составляет всего одну строку. Это поле всегда присутствует.
PG_DIAG_MESSAGE_DETAIL
#Необязательное дополнительное сообщение об ошибке, передающее более детальную информацию о проблеме. Может занимать несколько строк.
PG_DIAG_MESSAGE_HINT
#Подсказка: необязательное предположение о том, что можно сделать в данной проблемной ситуации. Оно должно отличаться от детальной информации в том смысле, что оно предлагает совет (возможно, и неподходящий), а не просто факты. Может занимать несколько строк.
PG_DIAG_STATEMENT_POSITION
#Строка, содержащая десятичное целое число, указывающее позицию расположения ошибки в качестве индекса в оригинальной строке оператора. Первый символ имеет позицию 1, при этом позиции измеряются в символах а не в байтах.
PG_DIAG_INTERNAL_POSITION
#Это поле определяется точно так же, как и поле
PG_DIAG_STATEMENT_POSITION
, но оно используется, когда позиция местонахождения ошибки относится к команде, сгенерированной внутренними модулями, а не к команде, представленной клиентом. Когда появляется это поле, то всегда появляется и полеPG_DIAG_INTERNAL_QUERY
.PG_DIAG_INTERNAL_QUERY
#Текст команды, сгенерированной внутренними модулями, завершившейся сбоем. Это мог бы быть, например, SQL-запрос, выданный функцией на языке PL/pgSQL.
PG_DIAG_CONTEXT
#Характеристика контекста, в котором произошла ошибка. В настоящее время она включает вывод стека вызовов активных функций процедурного языка и запросов, сгенерированных внутренними модулями. Стек выводится по одному элементу в строке, при этом первым идет самый последний из элементов (самый недавний вызов).
PG_DIAG_SCHEMA_NAME
#Если ошибка была связана с конкретным объектом базы данных, то в это поле будет записано имя схемы, содержащей данный объект.
PG_DIAG_TABLE_NAME
#Если ошибка была связана с конкретной таблицей, то в это поле будет записано имя таблицы. (Для получения имени схемы для данной таблицы обратитесь к полю, содержащему имя схемы.)
PG_DIAG_COLUMN_NAME
#Если ошибка была связана с конкретным столбцом таблицы, то в это поле будет записано имя столбца. (Чтобы идентифицировать таблицу, обратитесь к полям, содержащим имена схемы и таблицы.)
PG_DIAG_DATATYPE_NAME
#Если ошибка была связана с конкретным типом данных, то в это поле будет записано имя типа данных. (Чтобы получить имя схемы, которой принадлежит этот тип данных, обратитесь к полю, содержащему имя схемы.)
PG_DIAG_CONSTRAINT_NAME
#Если ошибка была связана с конкретным ограничением, то в это поле будет записано имя ограничения. Чтобы получить имя таблицы или домена, связанных с этим ограничением, обратитесь к полям, перечисленным выше. (С этой целью индексы рассматриваются как ограничения, даже если они и не были созданы с помощью синтаксиса для создания ограничений.)
PG_DIAG_SOURCE_FILE
#Имя файла, содержащего позицию в исходном коде, для которой было выдано сообщение об ошибка.
PG_DIAG_SOURCE_LINE
#Номер строки той позиции в исходном коде, для которой было выдано сообщение об ошибке.
PG_DIAG_SOURCE_FUNCTION
#Имя функции в исходном коде, сообщающей об ошибке.
Примечание
Поля для имени схемы, имени таблицы, имени столбца, имени типа данных и имени ограничения предоставляются лишь для ограниченного числа типов ошибок; см. Приложение A. Не рассчитывайте на то, что присутствие любого из этих полей гарантирует и присутствие какого-то другого поля. Базовые источники ошибок придерживаются взаимосвязей, описанных выше, но функции, определённые пользователем, могут использовать эти поля другими способами. Аналогично, не рассчитывайте на то, что эти поля обозначают объекты, существующие в текущей базе данных в настоящий момент.
Клиент отвечает за форматирование отображаемой информации в соответствии с его нуждами; в частности, он должен разбивать длинные строки, как требуется. Символы новой строки, встречающиеся в полях сообщения об ошибке, должны обрабатываться, как разрывы абзацев, а не строк.
Ошибки, сгенерированные внутренними модулями libpq, будут иметь поля серьёзности ошибки и основного сообщения, но, как правило, никаких других полей.
Заметьте, что поля ошибки доступны только из объектов
PGresult
, а не из объектовPGconn
. Не существует функцииPQerrorField
.PQclear
#Освобождает область памяти, связанную с
PGresult
. Результат выполнения каждой команды должен быть освобождён с помощьюPQclear
, когда он больше не нужен.void PQclear(PGresult *res);
Если аргумент является указателем
NULL
, операция не выполняется.Вы можете сохранять объект
PGresult
, пока он вам нужен; он не исчезает ни когда вы выдаёте новую команду, ни даже если вы закрываете соединение. Чтобы от него избавиться, вы должны вызватьPQclear
. Если этого не делать, в вашем приложении будут иметь место утечки памяти.
34.3.2. Извлечение информации, связанной с результатом запроса #
Эти функции служат для извлечения информации из объекта PGresult
, который представляет результат успешного запроса (то есть такого, который имеет статус PGRES_TUPLES_OK
, PGRES_SINGLE_TUPLE
или PGRES_TUPLES_CHUNK
). Их также можно использовать для извлечения информации об успешной операции DESCRIBE: результат этой операции содержит всю ту же самую информацию о столбцах, которая была бы получена при реальном исполнении запроса, но не содержит ни одной строки. Для объектов, имеющих другие значения статуса, эти функции будут действовать таким образом, как будто результат не содержит ни одной строки и ни одного столбца.
PQntuples
#Возвращает число строк (кортежей) в полученной выборке. (Заметьте, что объекты
PGresult
не могут содержать более чемINT_MAX
строк, так что для результата достаточно типаint
.)int PQntuples(const PGresult *res);
PQnfields
#Возвращает число столбцов (полей) в каждой строке полученной выборки.
int PQnfields(const PGresult *res);
PQfname
#Возвращает имя столбца, соответствующего данному номеру столбца. Номера столбцов начинаются с 0. Вызывающая функция не должна напрямую освобождать память, на которую указывает возвращаемый указатель. Она будет освобождена, когда соответствующий указатель на
PGresult
будет передан функцииPQclear
.char *PQfname(const PGresult *res, int column_number);
Если номер столбца выходит за пределы допустимого диапазона, то возвращается
NULL
.PQfnumber
#Возвращает номер столбца, соответствующий данному имени столбца.
int PQfnumber(const PGresult *res, const char *column_name);
Если данное имя не совпадает с именем ни одного из столбцов, то возвращается -1.
Данное имя интерпретируется, как идентификатор в SQL-команде. Это означает, что оно переводится в нижний регистр, если только оно не заключено в двойные кавычки. Например, для выборки, сгенерированной с помощью такой SQL-команды:
SELECT 1 AS FOO, 2 AS "BAR";
мы получили бы следующие результаты:
PQfname(res, 0) foo PQfname(res, 1) BAR PQfnumber(res, "FOO") 0 PQfnumber(res, "foo") 0 PQfnumber(res, "BAR") -1 PQfnumber(res, "\"BAR\"") 1
PQftable
#Возвращает OID таблицы, из которой был получен данный столбец. Номера столбцов начинаются с 0.
Oid PQftable(const PGresult *res, int column_number);
В следующих случаях возвращается
InvalidOid
: если номер столбца выходит за пределы допустимого диапазона; если указанный столбец не является простой ссылкой на столбец таблицы. Вы можете сделать запрос к системной таблицеpg_class
, чтобы точно определить, к какой таблице было произведено обращение.Тип данных
Oid
и константаInvalidOid
будут определены, когда вы включите заголовочный файл для libpq. Они будут принадлежать к одному из целочисленных типов.PQftablecol
#Возвращает номер столбца (в пределах его таблицы) для указанного столбца в полученной выборке. Номера столбцов в полученной выборке начинаются с 0, но столбцы в таблице имеют ненулевые номера.
int PQftablecol(const PGresult *res, int column_number);
В следующих случаях возвращается ноль: если номер столбца выходит за пределы допустимого диапазона; если указанный столбец не является простой ссылкой на столбец таблицы.
PQfformat
#Возвращает код формата, показывающий формат данного столбца. Номера столбцов начинаются с 0.
int PQfformat(const PGresult *res, int column_number);
Значение кода формата, равное нулю, указывает на текстовое представление данных, в то время, как значение, равное единице, означает двоичное представление. (Другие значения кодов зарезервированы для определения в будущем.)
PQftype
#Возвращает тип данных, соответствующий данному номеру столбца. Возвращаемое целое значение является внутренним номером OID для этого типа. Номера столбцов начинаются с 0.
Oid PQftype(const PGresult *res, int column_number);
Вы можете сделать запрос к системной таблице
pg_type
, чтобы получить имена и свойства различных типов данных.PQfmod
#Возвращает модификатор типа для столбца, соответствующего данному номеру. Номера столбцов начинаются с 0.
int PQfmod(const PGresult *res, int column_number);
Интерпретация значений модификатора зависит от типа; они обычно показывают точность или предельные размеры. Значение -1 используется, чтобы показать «нет доступной информации». Большинство типов данных не используют модификаторов, в таком случае значение всегда будет -1.
PQfsize
#Возвращает размер в байтах для столбца, соответствующего данному номеру. Номера столбцов начинаются с 0.
int PQfsize(const PGresult *res, int column_number);
PQfsize
возвращает размер пространства, выделенного для этого столбца в строке базы данных, другими словами, это размер внутреннего представления этого типа данных на сервере. (Следовательно, эта информация не является по-настоящему полезной для клиентов.) Отрицательное значение говорит о том, что тип данных имеет переменную длину.PQbinaryTuples
#Возвращает 1, если
PGresult
содержит двоичные данные, или 0, если данные текстовые.int PQbinaryTuples(const PGresult *res);
Эта функция не рекомендуется к использованию (за исключением применения в связи с командой
COPY
), поскольку один и тот жеPGresult
может содержать в некоторых столбцах текстовые данные, а в остальных — двоичные. Предпочтительнее использоватьPQfformat
.PQbinaryTuples
возвращает 1, только если все столбцы в выборке являются двоичными (код формата 1).PQgetvalue
#Возвращает значение одного поля из одной строки, содержащейся в
PGresult
. Номера строк и столбцов начинаются с 0. Вызывающая функция не должна напрямую освобождать память, на которую указывает возвращаемый указатель. Она будет освобождена, когда соответствующий указатель наPGresult
будет передан функцииPQclear
.char *PQgetvalue(const PGresult *res, int row_number, int column_number);
Для данных в текстовом формате значение, возвращаемое функцией
PQgetvalue
, является значением поля, представленным в виде символьной строки с завершающим нулевым символом. Для данных в двоичном формате используется двоичное представление значения. Оно определяется функциямиtypsend
иtypreceive
для конкретного типа данных. (В этом случае к значению также добавляется нулевой байт, но обычно это не приносит пользы, поскольку вероятно, что значение уже содержит нулевые байты.)Пустая строка возвращается в том случае, когда поле содержит null. Чтобы отличить значения null от пустых строковых значений, воспользуйтесь функцией
PQgetisnull
.Указатель, возвращаемый функцией
PQgetvalue
, указывает на область памяти внутри структурыPGresult
. Модифицировать данные, на которые указывает этот указатель, не следует. Вместо этого нужно явно скопировать данные в другую область памяти, если предполагается использовать их за рамками жизненного цикла структурыPGresult
.PQgetisnull
#Проверяет поле на предмет отсутствия значения (null). Номера строк и столбцов начинаются с 0.
int PQgetisnull(const PGresult *res, int row_number, int column_number);
Эта функция возвращает 1, если значение в поле отсутствует (null), и 0, если поле содержит отличное от null значение. (Заметьте, что если поле содержит null, функция
PQgetvalue
возвращает пустую строку, а не нулевой указатель.)PQgetlength
#Возвращает фактическую длину значения поля в байтах. Номера строк и столбцов начинаются с 0.
int PQgetlength(const PGresult *res, int row_number, int column_number);
Это фактическая длина данных для конкретного значения данных, то есть размер объекта, на который указывает
PQgetvalue
. Для текстового формата данных это то же самое, чтоstrlen()
. Для двоичного же формата это существенная информация. Учтите, что при расчёте фактического объёма данных не следует полагаться наPQfsize
.PQnparams
#Возвращает число параметров подготовленного оператора.
int PQnparams(const PGresult *res);
Эта функция полезна только при исследовании результата работы функции
PQdescribePrepared
. Для других типов результатов она возвратит ноль.PQparamtype
#Возвращает тип данных для указанного параметра оператора. Номера параметров начинаются с 0.
Oid PQparamtype(const PGresult *res, int param_number);
Эта функция полезна только при исследовании результата работы функции
PQdescribePrepared
. Для других типов результатов она возвратит ноль.PQprint
#Выводит все строки и, по выбору, имена столбцов в указанный поток вывода.
void PQprint(FILE *fout, /* поток вывода */ const PGresult *res, const PQprintOpt *po); typedef struct { pqbool header; /* печатать заголовки полей и счётчик строк */ pqbool align; /* выравнивать поля */ pqbool standard; /* старый формат */ pqbool html3; /* выводить HTML-таблицы */ pqbool expanded; /* расширять таблицы */ pqbool pager; /* использовать программу для постраничного просмотра, если нужно */ char *fieldSep; /* разделитель полей */ char *tableOpt; /* атрибуты для HTML-таблицы */ char *caption; /* заголовок HTML-таблицы */ char **fieldName; /* массив заменителей для имён полей, завершающийся нулевым символом */ } PQprintOpt;
Эту функцию прежде использовала утилита psql для вывода результатов запроса, но больше она её не использует. Обратите внимание, предполагается, что все данные представлены в текстовом формате.
34.3.3. Получение другой информации о результате #
Эти функции используются для получения остальной информации из объектов PGresult
.
PQcmdStatus
#Возвращает дескриптор статуса для SQL-команды, которая сгенерировала
PGresult
.char *PQcmdStatus(PGresult *res);
Как правило, это просто имя команды, но могут быть включены и дополнительные сведения, такие, как число обработанных строк. Вызывающая функция не должна напрямую освобождать память, на которую указывает возвращаемый указатель. Она будет освобождена, когда соответствующий указатель на
PGresult
будет передан функцииPQclear
.PQcmdTuples
#Возвращает число строк, которые затронула SQL-команда.
char *PQcmdTuples(PGresult *res);
Эта функция возвращает строковое значение, содержащее число строк, которые затронул SQL-оператор, сгенерировавший данный
PGresult
. Эту функцию можно использовать только сразу после выполнения командSELECT
,CREATE TABLE AS
,INSERT
,UPDATE
,DELETE
,MERGE
,MOVE
,FETCH
илиCOPY
, а также после оператораEXECUTE
, выполнившего подготовленный запрос, содержащий командыINSERT
,UPDATE
,DELETE
илиMERGE
. Если команда, которая сгенерировалаPGresult
, была какой-то иной, тоPQcmdTuples
возвращает пустую строку. Вызывающая функция не должна напрямую освобождать память, на которую указывает возвращаемый указатель. Она будет освобождена, когда соответствующий указатель наPGresult
будет передан функцииPQclear
.PQoidValue
#Возвращает OID вставленной строки, если SQL-команда была командой
INSERT
, которая вставила ровно одну строку в таблицу, имеющую идентификаторы OID, или командойEXECUTE
, которая выполнила подготовленный запрос, содержащий соответствующий операторINSERT
. В противном случае эта функция возвращаетInvalidOid
. Эта функция также возвратитInvalidOid
, если таблица, затронутая командойINSERT
, не содержит идентификаторов OID.Oid PQoidValue(const PGresult *res);
PQoidStatus
#Эта функция считается не рекомендуемой к использованию (в качестве замены служит
PQoidValue
), а также она не является потокобезопасной. Она возвращает строковое значение, содержащее OID вставленной строки, в то время какPQoidValue
возвращает значение OID.char *PQoidStatus(const PGresult *res);
34.3.4. Экранирование строковых значений для включения в SQL-команды #
PQescapeLiteral
#char *PQescapeLiteral(PGconn *conn, const char *str, size_t length);
PQescapeLiteral
экранирует строковое значение для использования внутри SQL-команды. Это полезно при вставке в SQL-команды значений данных в виде строковых констант. Определённые символы (например, кавычки и обратная косая черта) должны экранироваться, чтобы предотвратить их специальную интерпретацию синтаксическим анализатором языка SQL. Эту операцию выполняетPQescapeLiteral
.PQescapeLiteral
возвращает экранированную версию параметраstr
, размещённую в области памяти, распределённой с помощью функцииmalloc()
. Эту память нужно освобождать с помощью функцииPQfreemem()
, когда возвращённое значение больше не требуется. Завершающий нулевой байт не нужен и не должен учитываться в параметреlength
. (Если завершающий нулевой байт был найден до того, как были обработаныlength
байт, тоPQescapeLiteral
останавливает работу на нулевом байте; таким образом, поведение функции напоминаетstrncpy
.) В возвращённой строке все специальные символы заменены таким образом, что синтаксический анализатор строковых литералов Postgres Pro может обработать их должным образом. В строку также добавляется завершающий нулевой байт. Одинарные кавычки, которые должны окружать строковые литералы Postgres Pro, включаются в результирующую строку.В случае ошибки
PQescapeLiteral
возвращаетNULL
, и в объектconn
помещается соответствующее сообщение.Подсказка
Особенно важно выполнять надлежащее экранирование при обработке строк, полученных из ненадёжных источников. В противном случае ваша безопасность подвергается риску из-за уязвимости в отношении атак с использованием «SQL-инъекций», с помощью которых нежелательные SQL-команды направляются в вашу базу данных.
Обратите внимание, что нет необходимости (и это будет даже некорректно) экранировать значения данных, передаваемых в виде отдельных параметров в функцию
PQexecParams
или родственные ей функции.PQescapeIdentifier
#char *PQescapeIdentifier(PGconn *conn, const char *str, size_t length);
PQescapeIdentifier
экранирует строку, предназначенную для использования в качестве идентификатора SQL, например имени таблицы, столбца или функции. Это полезно, когда идентификатор, выбранный пользователем, может содержать специальные символы, которые в противном случае не интерпретировались бы синтаксическим анализатором SQL, как часть идентификатора, или когда идентификатор может содержать символы верхнего регистра и этот регистр требуется сохранить.PQescapeIdentifier
возвращает версию параметраstr
, экранированную как SQL-идентификатор, и размещённую в области памяти, распределённой с помощью функцииmalloc()
. Эту память нужно освобождать с помощью функцииPQfreemem()
, когда возвращённое значение больше не требуется. Завершающий нулевой байт не нужен и не должен учитываться в параметреlength
. (Если завершающий нулевой байт был найден до того, как были обработаныlength
байт, тоPQescapeIdentifier
останавливается на нулевом байте; таким образом, поведение функции напоминаетstrncpy
.) В возвращённой строке все специальные символы заменены таким образом, что она будет надлежащим образом обработана, как SQL-идентификатор. Завершающий нулевой байт также будет добавлен. Возвращённая строка также будет заключена в двойные кавычки.В случае ошибки
PQescapeIdentifier
возвращаетNULL
, и в объектconn
помещается соответствующее сообщение.Подсказка
Как и в случае со строковыми литералами, для того чтобы предотвратить атаки с помощью SQL-инъекций, SQL-идентификаторы должны экранироваться, когда они получены из ненадёжного источника.
PQescapeStringConn
#size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error);
PQescapeStringConn
экранирует строковые литералы наподобиеPQescapeLiteral
. Но, в отличие отPQescapeLiteral
, за предоставление буфера надлежащего размера отвечает вызывающая функция. Более того,PQescapeStringConn
не добавляет одинарные кавычки, которые должны окружать строковые литералы Postgres Pro; они должны быть включены в SQL-команду, в которую вставляется результирующая строка. Параметрfrom
указывает на первый символ строки, которая должна экранироваться, а параметрlength
задаёт число байт в этой строке. Завершающий нулевой байт не требуется и не должен учитываться в параметреlength
. (Если завершающий нулевой байт был найден до того, как были обработаныlength
байт, тоPQescapeStringConn
останавливается на нулевом байте; таким образом, поведение функции напоминаетstrncpy
.) Параметрto
должен указывать на буфер, который сможет вместить как минимум на один байт больше, чем предписывает удвоенное значение параметраlength
, в противном случае поведение функции не определено. Поведение будет также не определено, если строкиto
иfrom
перекрываются.Если параметр
error
не равенNULL
, тогда значение*error
устанавливается равным нулю в случае успешной работы и не равным нулю в случае ошибки. В настоящее время единственным возможным условием возникновения ошибки является неверная мультибайтовая кодировка в исходной строке. Выходная строка формируется даже при наличии ошибки, но можно ожидать, что сервер отвергнет её как неверно сформированную. В случае ошибки в объектconn
записывается соответствующее сообщение независимо от того, равно лиNULL
значение параметраerror
.PQescapeStringConn
возвращает число байт, записанных по адресуto
, не включая завершающий нулевой байт.PQescapeString
#PQescapeString
является более старой, не рекомендованной к использованию версией функцииPQescapeStringConn
.size_t PQescapeString (char *to, const char *from, size_t length);
Единственное отличие от
PQescapeStringConn
состоит в том, что у функцииPQescapeString
нет параметровPGconn
иerror
. Поэтому она не может скорректировать своё поведение в зависимости от свойств подключения (таких, как кодировка символов) и, следовательно, она может выдавать неверные результаты. Также она не имеет возможности сообщить об ошибках.PQescapeString
может безопасно использоваться в клиентских программах, которые работают лишь с одним подключением к Postgres Pro за один раз (в этом случае функция может найти то, что ей нужно знать, «за кулисами»). В других контекстах её использование несёт угрозу безопасности и его следует избегать в пользу применения функцииPQescapeStringConn
.PQescapeByteaConn
#Экранирует двоичные данные для их использования внутри SQL-команды с типом данных
bytea
. Как и в случае сPQescapeStringConn
, эта функция применяется только тогда, когда данные вставляются непосредственно в строку SQL-команды.unsigned char *PQescapeByteaConn(PGconn *conn, const unsigned char *from, size_t from_length, size_t *to_length);
Байты, имеющие определённые значения, должны экранироваться, когда они используются внутри литерала, имеющего тип
bytea
, в SQL-операторе.PQescapeByteaConn
экранирует байты, используя либо hex-кодирование, либо экранирование с помощью обратной косой черты. См. Раздел 8.4 для получения дополнительной информации.Параметр
from
указывает на первый байт строки, которая должна экранироваться, а параметрfrom_length
задаёт число байт в этой двоичной строке. (Завершающий нулевой байт не нужен и не учитывается.) Параметрto_length
указывает на переменную, которая будет содержать длину результирующей экранированной строки. Эта длина включает завершающий нулевой байт результирующей строки.PQescapeByteaConn
возвращает экранированную версию двоичной строки, на которую указывает параметрfrom
, и размещает её в памяти, распределённой с помощьюmalloc()
. Эта память должна быть освобождена с помощью функцииPQfreemem()
, когда результирующая строка больше не нужна. В возвращаемой строке все специальные символы заменены так, чтобы синтаксический анализатор литеральных строк Postgres Pro и функция ввода для типаbytea
могли обработать их надлежащим образом. Завершающий нулевой байт также добавляется. Одинарные кавычки, которые должны окружать строковые литералы Postgres Pro, не являются частью результирующей строки.В случае ошибки возвращается нулевой указатель, и соответствующее сообщение об ошибке записывается в объект
conn
. В настоящее время единственной возможной ошибкой может быть нехватка памяти для результирующей строки.PQescapeBytea
#PQescapeBytea
является устаревшей и не рекомендуемой к использованию версией функцииPQescapeByteaConn
.unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length);
Единственное отличие от
PQescapeByteaConn
состоит в том, что у функцииPQescapeBytea
нет параметраPGconn
. ПоэтомуPQescapeBytea
может безопасно использоваться в клиентских программах, которые работают лишь с одним подключением к Postgres Pro в один момент времени (в этом случае функция может узнать то, что ей нужно, «за кулисами»). Она может выдавать неверные результаты при использовании в программах, которые устанавливает несколько подключений к базам данных (в таких случаях используйтеPQescapeByteaConn
).PQunescapeBytea
#Преобразует строковое представление двоичных данных в двоичные данные — является обратной функцией к функции
PQescapeBytea
. Она нужна, когда данные типаbytea
извлекаются в текстовом формате, но не когда они извлекаются в двоичном формате.unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length);
Параметр
from
указывает на строку, такую, какую могла бы возвратить функцияPQgetvalue
, применённая к столбцу типаbytea
.PQunescapeBytea
преобразует это строковое представление в его двоичное представление. Она возвращает указатель на буфер, выделенный функциейmalloc()
, илиNULL
в случае ошибки и помещает размер буфера по адресуto_length
. Когда результат не будет нужен, необходимо освободить его память, вызвавPQfreemem
.Это преобразование не является точной инверсией для
PQescapeBytea
, поскольку ожидается, что строка, полученная отPQgetvalue
, не будет «экранированной». В частности, это означает, что учитывать режим спецпоследовательностей не нужно, и поэтому в параметреPGconn
нет необходимости.