diff --git a/dbms/src/Core/Protocol.h b/dbms/src/Core/Protocol.h index ec32cded920..ecc4caf14f1 100644 --- a/dbms/src/Core/Protocol.h +++ b/dbms/src/Core/Protocol.h @@ -6,76 +6,75 @@ namespace DB { -/** Протокол взаимодействия с сервером. - * - * Клиент соединяется с сервером и передаёт ему пакет Hello. - * Если версия не устраивает, то сервер может разорвать соединение. - * Сервер отвечает пакетом Hello. - * Если версия не устраивает, то клиент может разорвать соединение. - * - * Далее в цикле. - * - * 1. Клиент отправляет на сервер пакет Query. - * - * Начиная с версии 50263, сразу после отправки пакета Query клиент начинает передачу - * внешних (временных) таблиц (external storages) - один или несколько пакетов Data. - * Конец передачи данных определается по отправленному пустому блоку. - * В данный момент, не пустое множество таблиц может быть передано только вместе с запросом SELECT. - * - * Если запрос типа INSERT (требует передачи данных от клиента), то сервер передаёт - * пакет Data, содержащий пустой блок, который описывает структуру таблицы. - * Затем клиент отправляет данные для вставки - * - один или несколько пакетов Data. - * Конец данных определается по отправленному пустому блоку. - * Затем сервер отправляет клиенту пакет EndOfStream. - * - * Если запрос типа SELECT или другой, то сервер передаёт набор пакетов одного из следующих видов: - * - Data - данные результата выполнения запроса (один блок); - * - Progress - прогресс выполнения запроса; - * - Exception - ошибка; - * - EndOfStream - конец передачи данных; - * - * Клиент должен читать пакеты до EndOfStream или Exception. - * Также, клиент может передать на сервер пакет Cancel - отмена выполнения запроса. - * В этом случае, сервер может прервать выполнение запроса и вернуть неполные данные; - * но клиент всё равно должен читать все пакеты до EndOfStream. - * - * Перед пакетом EndOfStream, если есть профайлинговая информация и ревизия клиента достаточно новая, - * может быть отправлен пакет Totals и/или ProfileInfo. - * Totals - блок с тотальными значениями. - * ProfileInfo - данные профайлинга - сериализованная структура BlockStreamProfileInfo. - * - * При запросах, которые возвращают данные, сервер, перед обработкой запроса, - * отправляет заголовочный блок, содержащий описание столбцов из запроса, но с нулем строк. - * Используя этот заголовочный блок, клиент может заранее проинициализировать формат вывода - * и вывести префикс таблицы результата. - * - * 2. Между запросами, клиент может отправить Ping, и сервер должен ответить Pong. - */ + +/// Client-server protocol. +/// +/// Client opens a connection and sends Hello packet. +/// If client version is incompatible, the server can terminate the connection. +/// Server responds with Hello packet. +/// If server version is incompatible, the client can terminate the connection. +/// +/// The main loop follows: +/// +/// 1. The client sends Query packet. +/// +/// Starting from version 50263 immediately after sending the Query packet the client starts +/// transfer of external (temporary) table (external storages) - one or several Data packets. +/// End of transmission is marked by an empty block. +/// At present, non-empty tables can be sent only along with SELECT query. +/// +/// If the query is an INSERT (and thus requires data transfer from client), then the server transmits +/// Data packet containing empty block that describes the table structure. +/// Then the client sends one or several Data packets - data for insertion. +/// End of data is marked by the transmission of empty block. +/// Then the server sends EndOfStream packet. +/// +/// If the query is a SELECT or a query of other type, then the server transmits packets of +/// one of the following types: +/// - Data - data corresponding to one block of query results. +/// - Progress - query execution progress. +/// - Exception - error description. +/// - EndOfStream - the end of data transmission. +/// +/// The client should read packets until EndOfStream or Exception. +/// +/// The client can also send Cancel packet - a request to cancel the query. +/// In this case the server can stop executing the query and return incomplete data, +/// but the client must still read until EndOfStream packet. +/// +/// Also if there is profiling info and the client revision is recent enough, the server can +/// send one of the following packets before EndOfStream: +/// - Totals - a block with total values +/// - ProfileInfo - serialized BlockStreamProfileInfo structure. +/// +/// If a query returns data, the server sends an empty header block containing +/// the description of resulting columns before executing the query. +/// Using this block the client can initialise the output formatter and display the prefix of resulting table +/// beforehand. namespace Protocol { - /// То, что передаёт сервер. + /// Packet types that server transmits. namespace Server { enum Enum { - Hello = 0, /// Имя, версия, ревизия. - Data = 1, /// Блок данных со сжатием или без. - Exception = 2, /// Исключение во время обработки запроса. - Progress = 3, /// Прогресс выполнения запроса: строк считано, байт считано. - Pong = 4, /// Ответ на Ping. - EndOfStream = 5, /// Все пакеты были переданы. - ProfileInfo = 6, /// Пакет с профайлинговой информацией. - Totals = 7, /// Блок данных с тотальными значениями, со сжатием или без. - Extremes = 8, /// Блок данных с минимумами и максимумами, аналогично. - TablesStatusResponse = 9, + Hello = 0, /// Name, version, revision. + Data = 1, /// A block of data (compressed or not). + Exception = 2, /// The exception during query execution. + Progress = 3, /// Query execution progress: rows read, bytes read. + Pong = 4, /// Ping response + EndOfStream = 5, /// All packets were transmitted + ProfileInfo = 6, /// Packet with profiling info. + Totals = 7, /// A block with totals (compressed or not). + Extremes = 8, /// A block with minimums and maximums (compressed or not). + TablesStatusResponse = 9, /// A response to TablesStatus request. }; - /** NOTE: Если бы в качестве типа агрумента функции был бы Enum, то сравнение packet >= 0 && packet < 7 - * срабатывало бы всегда из-за оптимизации компилятором, даже если packet некорректный, и было бы чтение за границей массива. - * https://www.securecoding.cert.org/confluence/display/cplusplus/INT36-CPP.+Do+not+use+out-of-range+enumeration+values - */ + /// NOTE: If the type of packet argument would be Enum, the comparison packet >= 0 && packet < 10 + /// would always be true because of compiler optimisation. That would lead to out-of-bounds error + /// if the packet is invalid. + /// See https://www.securecoding.cert.org/confluence/display/cplusplus/INT36-CPP.+Do+not+use+out-of-range+enumeration+values inline const char * toString(UInt64 packet) { static const char * data[] = { "Hello", "Data", "Exception", "Progress", "Pong", "EndOfStream", "ProfileInfo", "Totals", "Extremes", "TablesStatusResponse" }; @@ -85,20 +84,19 @@ namespace Protocol } } - /// То, что передаёт клиент. + /// Packet types that client transmits. namespace Client { enum Enum { - Hello = 0, /// Имя, версия, ревизия, БД по-умолчанию. - Query = 1, /** Идентификатор запроса, настройки на отдельный запрос, - * информация, до какой стадии исполнять запрос, - * использовать ли сжатие, текст запроса (без данных для INSERT-а). - */ - Data = 2, /// Блок данных со сжатием или без. - Cancel = 3, /// Отменить выполнение запроса. - Ping = 4, /// Проверка живости соединения с сервером. - TablesStatusRequest = 5, /// Check status of tables on remote server. + Hello = 0, /// Name, version, revision, default DB + Query = 1, /// Query id, query settings, stage up to which the query must be executed, + /// whether the compression must be used, + /// query text (without data for INSERTs). + Data = 2, /// A block of data (compressed or not). + Cancel = 3, /// Cancel the query execution. + Ping = 4, /// Check that connection to the server is alive. + TablesStatusRequest = 5, /// Check status of tables on the server. }; inline const char * toString(UInt64 packet) @@ -110,7 +108,7 @@ namespace Protocol } } - /// Использовать ли сжатие. + /// Whether the compression must be used. namespace Compression { enum Enum