aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Core/Protocol.h
blob: 97a2831ffe8fb1fe5e46c2ef583bc7624e157f9d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#pragma once

#include <base/types.h>
#include <Core/ProtocolDefines.h>


namespace DB
{


/// 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 initialize the output formatter and display the prefix of resulting table
/// beforehand.

/// Marker of the inter-server secret (passed in the user name)
/// (anyway user cannot be started with a whitespace)
const char USER_INTERSERVER_MARKER[] = " INTERSERVER SECRET ";

namespace Protocol
{
    /// Packet types that server transmits.
    namespace Server
    {
        enum Enum
        {
            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.
            Log = 10,                       /// System logs of the query execution
            TableColumns = 11,              /// Columns' description for default values calculation
            PartUUIDs = 12,                 /// List of unique parts ids.
            ReadTaskRequest = 13,           /// String (UUID) describes a request for which next task is needed
                                            /// This is such an inverted logic, where server sends requests
                                            /// And client returns back response
            ProfileEvents = 14,             /// Packet with profile events from server.
            MergeTreeAllRangesAnnounecement = 15,
            MergeTreeReadTaskRequest = 16,  /// Request from a MergeTree replica to a coordinator
            TimezoneUpdate = 17,            /// Receive server's (session-wide) default timezone
            MAX = TimezoneUpdate,

        };

        /// 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",
                "Log",
                "TableColumns",
                "PartUUIDs",
                "ReadTaskRequest",
                "ProfileEvents",
                "MergeTreeAllRangesAnnounecement",
                "MergeTreeReadTaskRequest",
                "TimezoneUpdate",
            };
            return packet <= MAX
                ? data[packet]
                : "Unknown packet";
        }

        inline size_t stringsInMessage(UInt64 msg_type)
        {
            switch (msg_type)
            {
                case TableColumns:
                    return 2;
                default:
                    break;
            }
            return 0;
        }
    }

    /// Packet types that client transmits.
    namespace Client
    {
        enum Enum
        {
            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.
            KeepAlive = 6,                  /// Keep the connection alive
            Scalar = 7,                     /// A block of data (compressed or not).
            IgnoredPartUUIDs = 8,           /// List of unique parts ids to exclude from query processing
            ReadTaskResponse = 9,           /// A filename to read from s3 (used in s3Cluster)
            MergeTreeReadTaskResponse = 10, /// Coordinator's decision with a modified set of mark ranges allowed to read
            MAX = MergeTreeReadTaskResponse,
        };

        inline const char * toString(UInt64 packet)
        {
            static const char * data[] = {
                "Hello",
                "Query",
                "Data",
                "Cancel",
                "Ping",
                "TablesStatusRequest",
                "KeepAlive",
                "Scalar",
                "IgnoredPartUUIDs",
                "ReadTaskResponse",
                "MergeTreeReadTaskResponse"
            };
            return packet <= MAX
                ? data[packet]
                : "Unknown packet";
        }
    }

    /// Whether the compression must be used.
    enum class Compression
    {
        Disable = 0,
        Enable = 1,
    };

    /// Whether the ssl must be used.
    enum class Secure
    {
        Disable = 0,
        Enable = 1,
    };

}

}