ClickHouse/dbms/include/DB/Core/Protocol.h

123 lines
6.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <DB/Core/Types.h>
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.
*/
namespace Protocol
{
/// То, что передаёт сервер.
namespace Server
{
enum Enum
{
Hello = 0, /// Имя, версия, ревизия.
Data = 1, /// Блок данных со сжатием или без.
Exception = 2, /// Исключение во время обработки запроса.
Progress = 3, /// Прогресс выполнения запроса: строк считано, байт считано.
Pong = 4, /// Ответ на Ping.
EndOfStream = 5, /// Все пакеты были переданы.
ProfileInfo = 6, /// Пакет с профайлинговой информацией.
Totals = 7, /// Блок данных с тотальными значениями, со сжатием или без.
Extremes = 8, /// Блок данных с минимумами и максимумами, аналогично.
};
/** 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
*/
inline const char * toString(UInt64 packet)
{
static const char * data[] = { "Hello", "Data", "Exception", "Progress", "Pong", "EndOfStream", "ProfileInfo", "Totals", "Extremes" };
return packet < 9
? data[packet]
: "Unknown packet";
}
}
/// То, что передаёт клиент.
namespace Client
{
enum Enum
{
Hello = 0, /// Имя, версия, ревизия, БД по-умолчанию.
Query = 1, /** Идентификатор запроса, настройки на отдельный запрос,
* информация, до какой стадии исполнять запрос,
* использовать ли сжатие, текст запроса (без данных для INSERT-а).
*/
Data = 2, /// Блок данных со сжатием или без.
Cancel = 3, /// Отменить выполнение запроса.
Ping = 4, /// Проверка живости соединения с сервером.
};
inline const char * toString(UInt64 packet)
{
static const char * data[] = { "Hello", "Query", "Data", "Cancel", "Ping" };
return packet < 5
? data[packet]
: "Unknown packet";
}
}
/// Использовать ли сжатие.
namespace Compression
{
enum Enum
{
Disable = 0,
Enable = 1,
};
}
}
}