1#pragma once
2
3#include <Core/Types.h>
4
5
6namespace DB
7{
8
9
10/// Client-server protocol.
11///
12/// Client opens a connection and sends Hello packet.
13/// If client version is incompatible, the server can terminate the connection.
14/// Server responds with Hello packet.
15/// If server version is incompatible, the client can terminate the connection.
16///
17/// The main loop follows:
18///
19/// 1. The client sends Query packet.
20///
21/// Starting from version 50263 immediately after sending the Query packet the client starts
22/// transfer of external (temporary) table (external storages) - one or several Data packets.
23/// End of transmission is marked by an empty block.
24/// At present, non-empty tables can be sent only along with SELECT query.
25///
26/// If the query is an INSERT (and thus requires data transfer from client), then the server transmits
27/// Data packet containing empty block that describes the table structure.
28/// Then the client sends one or several Data packets - data for insertion.
29/// End of data is marked by the transmission of empty block.
30/// Then the server sends EndOfStream packet.
31///
32/// If the query is a SELECT or a query of other type, then the server transmits packets of
33/// one of the following types:
34/// - Data - data corresponding to one block of query results.
35/// - Progress - query execution progress.
36/// - Exception - error description.
37/// - EndOfStream - the end of data transmission.
38///
39/// The client should read packets until EndOfStream or Exception.
40///
41/// The client can also send Cancel packet - a request to cancel the query.
42/// In this case the server can stop executing the query and return incomplete data,
43/// but the client must still read until EndOfStream packet.
44///
45/// Also if there is profiling info and the client revision is recent enough, the server can
46/// send one of the following packets before EndOfStream:
47/// - Totals - a block with total values
48/// - ProfileInfo - serialized BlockStreamProfileInfo structure.
49///
50/// If a query returns data, the server sends an empty header block containing
51/// the description of resulting columns before executing the query.
52/// Using this block the client can initialise the output formatter and display the prefix of resulting table
53/// beforehand.
54
55namespace Protocol
56{
57 /// Packet types that server transmits.
58 namespace Server
59 {
60 enum Enum
61 {
62 Hello = 0, /// Name, version, revision.
63 Data = 1, /// A block of data (compressed or not).
64 Exception = 2, /// The exception during query execution.
65 Progress = 3, /// Query execution progress: rows read, bytes read.
66 Pong = 4, /// Ping response
67 EndOfStream = 5, /// All packets were transmitted
68 ProfileInfo = 6, /// Packet with profiling info.
69 Totals = 7, /// A block with totals (compressed or not).
70 Extremes = 8, /// A block with minimums and maximums (compressed or not).
71 TablesStatusResponse = 9, /// A response to TablesStatus request.
72 Log = 10, /// System logs of the query execution
73 TableColumns = 11, /// Columns' description for default values calculation
74 };
75
76 /// NOTE: If the type of packet argument would be Enum, the comparison packet >= 0 && packet < 10
77 /// would always be true because of compiler optimisation. That would lead to out-of-bounds error
78 /// if the packet is invalid.
79 /// See https://www.securecoding.cert.org/confluence/display/cplusplus/INT36-CPP.+Do+not+use+out-of-range+enumeration+values
80 inline const char * toString(UInt64 packet)
81 {
82 static const char * data[] = { "Hello", "Data", "Exception", "Progress", "Pong", "EndOfStream", "ProfileInfo", "Totals",
83 "Extremes", "TablesStatusResponse", "Log", "TableColumns" };
84 return packet < 12
85 ? data[packet]
86 : "Unknown packet";
87 }
88
89 inline size_t stringsInMessage(UInt64 msg_type)
90 {
91 switch (msg_type)
92 {
93 case TableColumns:
94 return 2;
95 default:
96 break;
97 }
98 return 0;
99 }
100 }
101
102 /// Packet types that client transmits.
103 namespace Client
104 {
105 enum Enum
106 {
107 Hello = 0, /// Name, version, revision, default DB
108 Query = 1, /// Query id, query settings, stage up to which the query must be executed,
109 /// whether the compression must be used,
110 /// query text (without data for INSERTs).
111 Data = 2, /// A block of data (compressed or not).
112 Cancel = 3, /// Cancel the query execution.
113 Ping = 4, /// Check that connection to the server is alive.
114 TablesStatusRequest = 5, /// Check status of tables on the server.
115 KeepAlive = 6, /// Keep the connection alive
116 Scalar = 7 /// A block of data (compressed or not).
117 };
118
119 inline const char * toString(UInt64 packet)
120 {
121 static const char * data[] = { "Hello", "Query", "Data", "Cancel", "Ping", "TablesStatusRequest", "KeepAlive" };
122 return packet < 7
123 ? data[packet]
124 : "Unknown packet";
125 }
126 }
127
128 /// Whether the compression must be used.
129 enum class Compression
130 {
131 Disable = 0,
132 Enable = 1,
133 };
134
135 /// Whether the ssl must be used.
136 enum class Secure
137 {
138 Disable = 0,
139 Enable = 1,
140 };
141
142}
143
144}
145