Обзор

В протоколе имеются отдельные фазы для запуска и обычных операций. В фазе запуска клиент устанавливает соединение с сервером и аутентифицируется, чтобы удовлетворить сервер. (Это может потребовать одного или нескольких сообщений в зависимости от используемого метода аутентификации.) Если все проходит успешно, сервер передает клиенту информацию о текущем состоянии и наконец переходит к обычным операциям. За исключением сообщения о запуске при установке подключения, эта часть протокола управляется сервером.

Во время обычной работы клиент посылает серверу запросы и другие команды, а сервер возвращает результаты запросов и другие ответы. Существует несколько сценариев (например, NOTIFY), когда сервер передает сообщения по собственной инициативе, но по большей части эта фаза сеанса управляется запросами клиента.

Завершение сеанса обычно происходит по решению клиента, но в некоторых случаях может быть принудительно вызвано сервером. В любом случае, когда сервер закрывает соединение, перед этим он откатывает любую открытую (незавершенную) транзакцию.

В ходе обычной работы команды SQL могут выполняться по одному из двух подчиненных протоколов. По протоколу «простого запроса» клиент просто посылает текстовую строку запроса, которая анализируется и немедленно выполняется сервером. По протоколу «расширенного запроса» обработка запросов разделяется на несколько этапов: анализ, привязка значений параметров и выполнение. Это дает повышенную гибкость и производительность за счет увеличения сложности.

Для обычной работы имеются также дополнительные подчиненные протоколы для специальных операций вроде COPY.



Обзор обмена сообщениями

Все взаимодействие происходит через поток сообщений. Первый байт сообщения определяет его тип, а следующие четыре — длину остального сообщения (этот счетчик длины включает размер самого поля длины, но не байт с типом сообщения). Остальное содержимое сообщения определяется его типом. По историческим причинам у самого первого сообщения, передаваемого клиентом (сообщения о запуске), первого байта с типом сообщения нет.

Чтобы не потерять синхронизацию в потоке сообщений, серверы и клиенты обычно считывают все сообщение в буфер (используя счетчик байтов), прежде чем пытаться обработать его содержимое. Это позволяет с легкостью восстановить работу, если при обработке содержимого обнаруживается ошибка. В экстремальных ситуациях (например, при нехватке памяти для буферизации сообщения), получатель может воспользоваться счетчиком байтов для определения того, какой объем данных нужно пропустить, прежде чем продолжить считывать сообщения.

С другой стороны, клиенты и серверы ни при каких условиях не должны передавать неполные сообщения. Обычно для этого перед началом отправки все сообщение маршализуется в буфере. Если в процессе отправки или получения сообщения происходит сбой передачи, единственной разумной реакцией будет прерывание соединения, поскольку вероятность восстановления синхронизации по границам сообщений крайне мала.



Обзор расширенных запросов

В протоколе расширенных запросов выполнение команд SQL разделено на несколько этапов. Состояние между этапами представляется двумя типами объектов: подготовленными операторами и порталами. Подготовленный оператор представляет собой результат синтаксического и семантического анализов текстовой строки запроса. Сам по себе подготовленный оператор не готов для выполнения, потому что в нем могут отсутствовать конкретные значения для параметров. Портал представляет собой готовый к выполнению или уже частично выполненный оператор, в котором заданы все недостающие значения параметров. (Для операторов SELECT портал равнозначен открытому курсору, но мы предпочитаем использовать другой термин, поскольку курсоры неприменимы к операторам, отличным от SELECT.)

Общий цикл выполнения состоит из этапа синтаксического анализа, на котором из текстовой строки создается подготовленный оператор, этапа привязки, на котором из подготовленного оператора и значений всех необходимых параметров создается портал, и этапа выполнения, на котором выполняется запрос портала. В случае запроса, возвращающего строки (SELECT, SHOW и т. д.), можно указать, чтобы на этапе выполнения извлекалось лишь ограниченное число строк, поэтому для завершения операции может понадобиться несколько этапов выполнения.

Сервер может отслеживать несколько подготовленных операторов и порталов (но обратите внимание, что они существуют только в рамках сеанса и никогда не разделяются между сеансами). К существующим подготовленным операторам и порталам обращаются по именам, назначенным им при создании. Кроме того, существуют и «безымянные» подготовленные операторы и порталы. Хотя они ведут себя практически так же, как именованные объекты, операции с ними оптимизированы для разового выполнения запроса с последующим их освобождением, тогда как операции с именованными объектами оптимизированы в расчете на многократное использование.



Форматы и коды форматов

Данные определенного типа могут передаваться в одном из нескольких различных форматов. На данный момент в QHB поддерживаются только текстовый «text» и двоичный «binary» форматы, но в протоколе предусмотрены возможности для расширения в будущем. Желаемый формат для любого значения задается кодом формата. Клиенты могут указывать код формата для каждого передаваемого значения параметра и для каждого столбца результата запроса. Текстовый формат имеет код ноль, двоичный — один, а все остальные коды форматов зарезервированы для определения в будущем.

Текстовым представлением значения являются строки, которые выдаются и принимаются функциями преобразования ввода/вывода для определенного типа данных. В передаваемом представлении отсутствует завершающий пустой символ; клиент должен добавить его к получаемым значениям, если хочет обрабатывать их как строки C. (Кстати говоря, данным в текстовом формате нельзя содержать пустые символы.)

В двоичных представлениях для целых чисел используется сетевой порядок байтов (наиболее значащий байт идет первым). Какое двоичное представление имеют другие типы данных, можно узнать в документации или исходном коде. Учтите, что двоичные представления для сложных типов данных могут изменяться от версии к версии сервера; текстовый формат более платформонезависимый.