-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathmysql_connection.h
277 lines (250 loc) · 9.42 KB
/
mysql_connection.h
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#ifndef __CLASS_MYSQL_CONNECTION_H
#define __CLASS_MYSQL_CONNECTION_H
#include "proxysql.h"
#include "cpp.h"
//#include "../deps/json/json.hpp"
//using json = nlohmann::json;
#ifndef PROXYJSON
#define PROXYJSON
#include "../deps/json/json_fwd.hpp"
#endif // PROXYJSON
//#define STATUS_MYSQL_CONNECTION_TRANSACTION 0x00000001 // DEPRECATED
#define STATUS_MYSQL_CONNECTION_COMPRESSION 0x00000002
#define STATUS_MYSQL_CONNECTION_USER_VARIABLE 0x00000004
#define STATUS_MYSQL_CONNECTION_PREPARED_STATEMENT 0x00000008
#define STATUS_MYSQL_CONNECTION_LOCK_TABLES 0x00000010
#define STATUS_MYSQL_CONNECTION_TEMPORARY_TABLE 0x00000020
#define STATUS_MYSQL_CONNECTION_GET_LOCK 0x00000040
#define STATUS_MYSQL_CONNECTION_NO_MULTIPLEX 0x00000080
#define STATUS_MYSQL_CONNECTION_SQL_LOG_BIN0 0x00000100
#define STATUS_MYSQL_CONNECTION_FOUND_ROWS 0x00000200
#define STATUS_MYSQL_CONNECTION_NO_MULTIPLEX_HG 0x00000400
#define STATUS_MYSQL_CONNECTION_HAS_SAVEPOINT 0x00000800
#define STATUS_MYSQL_CONNECTION_HAS_WARNINGS 0x00001000
class MySQLServers_SslParams;
class Variable {
public:
char *value = (char*)"";
void fill_server_internal_session(nlohmann::json &j, int idx);
void fill_client_internal_session(nlohmann::json &j, int idx);
};
enum charset_action {
UNKNOWN,
NAMES,
CHARSET,
CONNECT_START
};
class MySQL_Connection_userinfo {
private:
uint64_t compute_hash();
public:
uint64_t hash;
char *username;
char *password;
PASSWORD_TYPE::E passtype;
char *schemaname;
char *sha1_pass;
char *fe_username;
MySQL_Connection_userinfo();
~MySQL_Connection_userinfo();
void set(char *, char *, char *, char *);
void set(MySQL_Connection_userinfo *);
bool set_schemaname(char *, int);
};
class MySQL_Connection {
private:
void update_warning_count_from_connection();
void update_warning_count_from_statement();
bool is_expired(unsigned long long timeout);
unsigned long long inserted_into_pool;
void connect_start_SetAttributes();
void connect_start_SetCharset();
void connect_start_SetClientFlag(unsigned long&);
char * connect_start_DNS_lookup();
void connect_start_SetSslSettings();
void ProcessQueryAndSetStatusFlags_Warnings(char *);
void ProcessQueryAndSetStatusFlags_UserVariables(char *, int);
void ProcessQueryAndSetStatusFlags_Savepoint(char *);
void ProcessQueryAndSetStatusFlags_SetBackslashEscapes();
public:
struct {
char *server_version;
uint32_t session_track_gtids_int;
uint32_t max_allowed_pkt;
uint32_t server_capabilities;
uint32_t client_flag;
unsigned int compression_min_length;
char *init_connect;
bool init_connect_sent;
char * session_track_gtids;
char *ldap_user_variable;
char *ldap_user_variable_value;
bool session_track_gtids_sent;
bool ldap_user_variable_sent;
uint8_t protocol_version;
int8_t last_set_autocommit;
bool autocommit;
bool no_backslash_escapes;
} options;
Variable variables[SQL_NAME_LAST_HIGH_WM];
uint32_t var_hash[SQL_NAME_LAST_HIGH_WM];
// for now we store possibly missing variables in the lower range
// we may need to fix that, but this will cost performance
bool var_absent[SQL_NAME_LAST_HIGH_WM] = {false};
std::vector<uint32_t> dynamic_variables_idx;
unsigned int reorder_dynamic_variables_idx();
struct {
unsigned long length;
char *ptr;
MYSQL_STMT *stmt;
MYSQL_RES *stmt_result;
stmt_execute_metadata_t *stmt_meta;
} query;
char scramble_buff[40];
unsigned long long creation_time;
unsigned long long last_time_used;
unsigned long long timeout;
int auto_increment_delay_token;
int fd;
MySQL_STMTs_local_v14 *local_stmts; // local view of prepared statements
MYSQL *mysql;
MYSQL *ret_mysql;
MYSQL_RES *mysql_result;
MYSQL_ROW mysql_row;
MySQL_ResultSet *MyRS;
MySQL_ResultSet *MyRS_reuse;
MySrvC *parent;
MySQL_Connection_userinfo *userinfo;
MySQL_Data_Stream *myds;
struct {
char* hostname;
char* ip;
} connected_host_details;
/**
* @brief Keeps tracks of the 'server_status'. Do not confuse with the 'server_status' from the
* 'MYSQL' connection itself. This flag keeps track of the configured server status from the
* parent 'MySrvC'.
*/
enum MySerStatus server_status; // this to solve a side effect of #774
bytes_stats_t bytes_info; // bytes statistics
struct {
unsigned long long questions;
unsigned long long myconnpoll_get;
unsigned long long myconnpoll_put;
} statuses;
unsigned long largest_query_length;
unsigned int warning_count;
/**
* @brief This represents the internal knowledge of ProxySQL about the connection. It keeps track of those
* states which *are not reflected* into 'server_status', but are relevant for connection handling.
*/
uint32_t status_flags;
int async_exit_status; // exit status of MariaDB Client Library Non blocking API
int interr; // integer return
MDB_ASYNC_ST async_state_machine; // Async state machine
short wait_events;
uint8_t compression_pkt_id;
my_bool ret_bool;
bool async_fetch_row_start;
bool send_quit;
bool reusable;
bool processing_multi_statement;
bool multiplex_delayed;
bool unknown_transaction_status;
void compute_unknown_transaction_status();
char gtid_uuid[128];
MySQLServers_SslParams * ssl_params = NULL;
MySQL_Connection();
~MySQL_Connection();
bool set_autocommit(bool);
bool set_no_backslash_escapes(bool);
unsigned int set_charset(unsigned int, enum charset_action);
void set_status(bool set, uint32_t status_flag);
void set_status_sql_log_bin0(bool);
bool get_status(uint32_t status_flag);
bool get_status_sql_log_bin0();
void connect_start();
void connect_cont(short event);
void change_user_start();
void change_user_cont(short event);
void ping_start();
void ping_cont(short event);
void set_autocommit_start();
void set_autocommit_cont(short event);
void set_names_start();
void set_names_cont(short event);
void real_query_start();
void real_query_cont(short event);
#ifndef PROXYSQL_USE_RESULT
void store_result_start();
void store_result_cont(short event);
#endif // PROXYSQL_USE_RESULT
void initdb_start();
void initdb_cont(short event);
void set_option_start();
void set_option_cont(short event);
void set_query(char *stmt, unsigned long length);
MDB_ASYNC_ST handler(short event);
void next_event(MDB_ASYNC_ST new_st);
int async_connect(short event);
int async_change_user(short event);
int async_select_db(short event);
int async_set_autocommit(short event, bool);
int async_set_names(short event, unsigned int nr);
int async_send_simple_command(short event, char *stmt, unsigned long length); // no result set expected
int async_query(short event, char *stmt, unsigned long length, MYSQL_STMT **_stmt=NULL, stmt_execute_metadata_t *_stmt_meta=NULL);
int async_ping(short event);
int async_set_option(short event, bool mask);
void stmt_prepare_start();
void stmt_prepare_cont(short event);
void stmt_execute_start();
void stmt_execute_cont(short event);
void stmt_execute_store_result_start();
void stmt_execute_store_result_cont(short event);
/**
* @brief Process the rows returned by 'async_stmt_execute_store_result'. Extracts all the received
* rows from 'query.stmt->result.data' but the last one, adds them to 'MyRS', frees the buffer
* used by 'query.stmt' and allocates a new one with the last row, leaving it ready for being filled
* with the new rows to be received.
* @param processed_bytes Reference to the already processed bytes to be updated with the rows
* that are being read and added to 'MyRS'.
*/
void process_rows_in_ASYNC_STMT_EXECUTE_STORE_RESULT_CONT(unsigned long long& processed_bytes);
void async_free_result();
/**
* @brief Returns if the connection is **for sure**, known to be in an active transaction.
* @details The function considers two things:
* 1. If 'server_status' is flagged with 'SERVER_STATUS_IN_TRANS'.
* 2. If the connection has 'autcommit=0' and 'autocommit_false_is_transaction' is set.
* @return True if the connection is known to be in a transaction, or equivalent state.
*/
bool IsKnownActiveTransaction();
/**
* @brief Returns if the connection is in a **potential transaction**.
* @details This function is a more strict version of 'IsKnownActiveTransaction', which also considers
* connections which holds 'unknown_transaction_status' as potentially active transactions.
* @return True if the connection is in potentially in an active transaction.
*/
bool IsActiveTransaction();
bool IsServerOffline();
bool IsAutoCommit();
bool AutocommitFalse_AndSavepoint();
bool MultiplexDisabled(bool check_delay_token = true);
bool IsKeepMultiplexEnabledVariables(char *query_digest_text);
void ProcessQueryAndSetStatusFlags(char *query_digest_text);
void optimize();
void close_mysql();
void set_is_client(); // used for local_stmts
void reset();
bool get_gtid(char *buff, uint64_t *trx_id);
void reduce_auto_increment_delay_token() { if (auto_increment_delay_token) auto_increment_delay_token--; };
bool match_ff_req_options(const MySQL_Connection *c);
bool match_tracked_options(const MySQL_Connection *c);
bool requires_CHANGE_USER(const MySQL_Connection *client_conn);
unsigned int number_of_matching_session_variables(const MySQL_Connection *client_conn, unsigned int& not_matching);
unsigned long get_mysql_thread_id() { return mysql ? mysql->thread_id : 0; }
static void set_ssl_params(MYSQL *mysql, MySQLServers_SslParams *ssl_params);
void get_mysql_info_json(nlohmann::json&);
void get_backend_conn_info_json(nlohmann::json&);
};
#endif /* __CLASS_MYSQL_CONNECTION_H */