1 /* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #define LOG_COMPONENT_TAG "test_session_info"
24
25 #include <fcntl.h>
26 #include <mysql/plugin.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29
30 #include "m_string.h"
31 #include "my_dbug.h"
32 #include "my_inttypes.h"
33 #include "my_io.h"
34 #include "my_psi_config.h"
35 #include "my_sys.h" // my_write, my_malloc
36 #include "mysql/components/services/psi_thread_bits.h"
37 #include "mysql/psi/mysql_thread.h"
38 #include "mysql_com.h"
39 #include "sql_string.h" /* STRING_PSI_MEMORY_KEY */
40 #include "template_utils.h"
41 #include "violite.h"
42
43 #include <mysql/components/my_service.h>
44 #include <mysql/components/services/log_builtins.h>
45 #include <mysqld_error.h>
46
47 static const char *log_filename = "test_session_info";
48
49 static File outfile;
50
51 #define STRING_BUFFER_SIZE 1100
52
53 #define WRITE_STR(format) \
54 { \
55 snprintf(buffer, sizeof(buffer), "%s", (format)); \
56 my_write(outfile, (uchar *)buffer, strlen(buffer), MYF(0)); \
57 }
58
59 #define WRITE_VAL(format, value) \
60 { \
61 snprintf(buffer, sizeof(buffer), (format), (value)); \
62 my_write(outfile, (uchar *)buffer, strlen(buffer), MYF(0)); \
63 }
64
65 #define WRITE_VAL2(format, value1, value2) \
66 { \
67 snprintf(buffer, sizeof(buffer), (format), (value1), (value2)); \
68 my_write(outfile, (uchar *)buffer, strlen(buffer), MYF(0)); \
69 }
70
71 static const char *sep =
72 "=========================================================================="
73 "==================\n";
74
75 #define WRITE_SEP() \
76 my_write(outfile, pointer_cast<const uchar *>(sep), strlen(sep), MYF(0))
77
78 static SERVICE_TYPE(registry) *reg_srv = nullptr;
79 SERVICE_TYPE(log_builtins) *log_bi = nullptr;
80 SERVICE_TYPE(log_builtins_string) *log_bs = nullptr;
81
82 static const char *user_localhost = "localhost";
83 static const char *user_local = "127.0.0.1";
84 static const char *user_db = "";
85 static const char *user_privileged = "root";
86 // static const char *user_ordinary= "ordinary";
87
switch_user(MYSQL_SESSION session,const char * user)88 static void switch_user(MYSQL_SESSION session, const char *user) {
89 MYSQL_SECURITY_CONTEXT sc;
90 thd_get_security_context(srv_session_info_get_thd(session), &sc);
91 security_context_lookup(sc, user, user_localhost, user_local, user_db);
92 }
93
94 /* Session declarations */
95 COM_DATA cmd;
96
97 struct st_send_field_n {
98 char db_name[256];
99 char table_name[256];
100 char org_table_name[256];
101 char col_name[256];
102 char org_col_name[256];
103 unsigned long length;
104 unsigned int charsetnr;
105 unsigned int flags;
106 unsigned int decimals;
107 enum_field_types type;
108 };
109
110 struct st_decimal_n {
111 int intg, frac, len;
112 bool sign;
113 decimal_digit_t buf[256];
114 };
115
116 struct st_plugin_ctx {
117 const CHARSET_INFO *resultcs;
118 uint meta_server_status;
119 uint meta_warn_count;
120 uint current_col;
121 uint num_cols;
122 uint num_rows;
123 st_send_field_n sql_field[64];
124 char sql_str_value[64][64][256];
125 size_t sql_str_len[64][64];
126 longlong sql_int_value[64][64];
127 longlong sql_longlong_value[64][64];
128 uint sql_is_unsigned[64][64];
129 st_decimal_n sql_decimal_value[64][64];
130 double sql_double_value[64][64];
131 uint32 sql_double_decimals[64][64];
132 MYSQL_TIME sql_date_value[64][64];
133 MYSQL_TIME sql_time_value[64][64];
134 uint sql_time_decimals[64][64];
135 MYSQL_TIME sql_datetime_value[64][64];
136 uint sql_datetime_decimals[64][64];
137
138 uint server_status;
139 uint warn_count;
140 uint affected_rows;
141 uint last_insert_id;
142 char message[1024];
143
144 uint sql_errno;
145 char err_msg[1024];
146 char sqlstate[6];
st_plugin_ctxst_plugin_ctx147 st_plugin_ctx() { reset(); }
148
resetst_plugin_ctx149 void reset() {
150 resultcs = nullptr;
151 server_status = 0;
152 current_col = 0;
153 warn_count = 0;
154 num_cols = 0;
155 num_rows = 0;
156 memset(&sql_field, 0, 64 * sizeof(st_send_field_n));
157 memset(&sql_str_value, 0, 64 * 64 * 256 * sizeof(char));
158 memset(&sql_str_len, 0, 64 * 64 * sizeof(size_t));
159 memset(&sql_int_value, 0, 64 * 64 * sizeof(longlong));
160 memset(&sql_longlong_value, 0, 64 * 64 * sizeof(longlong));
161 memset(&sql_is_unsigned, 0, 64 * 64 * sizeof(uint));
162 memset(&sql_decimal_value, 0, 64 * 64 * sizeof(st_decimal_n));
163 memset(&sql_double_value, 0, 64 * 64 * sizeof(double));
164 memset(&sql_double_decimals, 0, 64 * 64 * sizeof(uint32));
165 memset(&sql_date_value, 0, 64 * 64 * sizeof(MYSQL_TIME));
166 memset(&sql_time_value, 0, 64 * 64 * sizeof(MYSQL_TIME));
167 memset(&sql_time_decimals, 0, 64 * 64 * sizeof(uint));
168 memset(&sql_datetime_value, 0, 64 * 64 * sizeof(MYSQL_TIME));
169 memset(&sql_datetime_decimals, 0, 64 * 64 * sizeof(uint));
170
171 server_status = 0;
172 warn_count = 0;
173 affected_rows = 0;
174 last_insert_id = 0;
175 memset(&message, 0, sizeof(message));
176
177 sql_errno = 0;
178 memset(&err_msg, 0, sizeof(err_msg));
179 memset(&sqlstate, 0, sizeof(sqlstate));
180 }
181 };
182
sql_start_result_metadata(void * ctx,uint num_cols,uint,const CHARSET_INFO * resultcs)183 static int sql_start_result_metadata(void *ctx, uint num_cols, uint,
184 const CHARSET_INFO *resultcs) {
185 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
186 DBUG_TRACE;
187 DBUG_PRINT("info", ("resultcs->number: %d", resultcs->number));
188 DBUG_PRINT("info", ("resultcs->csname: %s", resultcs->csname));
189 DBUG_PRINT("info", ("resultcs->name: %s", resultcs->name));
190 pctx->num_cols = num_cols;
191 pctx->resultcs = resultcs;
192 pctx->current_col = 0;
193 return false;
194 }
195
sql_field_metadata(void * ctx,struct st_send_field * field,const CHARSET_INFO *)196 static int sql_field_metadata(void *ctx, struct st_send_field *field,
197 const CHARSET_INFO *) {
198 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
199 st_send_field_n *cfield = &pctx->sql_field[pctx->current_col];
200 DBUG_TRACE;
201 DBUG_PRINT("info", ("field->db_name: %s", field->db_name));
202 DBUG_PRINT("info", ("field->table_name: %s", field->table_name));
203 DBUG_PRINT("info", ("field->org_table_name: %s", field->org_table_name));
204 DBUG_PRINT("info", ("field->col_name: %s", field->col_name));
205 DBUG_PRINT("info", ("field->org_col_name: %s", field->org_col_name));
206 DBUG_PRINT("info", ("field->length: %d", (int)field->length));
207 DBUG_PRINT("info", ("field->charsetnr: %d", (int)field->charsetnr));
208 DBUG_PRINT("info", ("field->flags: %d", (int)field->flags));
209 DBUG_PRINT("info", ("field->decimals: %d", (int)field->decimals));
210 DBUG_PRINT("info", ("field->type: %d", (int)field->type));
211
212 strcpy(cfield->db_name, field->db_name);
213 strcpy(cfield->table_name, field->table_name);
214 strcpy(cfield->org_table_name, field->org_table_name);
215 strcpy(cfield->col_name, field->col_name);
216 strcpy(cfield->org_col_name, field->org_col_name);
217 cfield->length = field->length;
218 cfield->charsetnr = field->charsetnr;
219 cfield->flags = field->flags;
220 cfield->decimals = field->decimals;
221 cfield->type = field->type;
222
223 pctx->current_col++;
224 return false;
225 }
226
sql_end_result_metadata(void * ctx,uint server_status,uint warn_count)227 static int sql_end_result_metadata(void *ctx, uint server_status,
228 uint warn_count) {
229 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
230 DBUG_TRACE;
231 pctx->meta_server_status = server_status;
232 pctx->meta_warn_count = warn_count;
233 pctx->num_rows = 0;
234 return false;
235 }
236
sql_start_row(void * ctx)237 static int sql_start_row(void *ctx) {
238 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
239 DBUG_TRACE;
240 pctx->current_col = 0;
241 return false;
242 }
243
sql_end_row(void * ctx)244 static int sql_end_row(void *ctx) {
245 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
246 DBUG_TRACE;
247 pctx->num_rows++;
248 return false;
249 }
250
sql_abort_row(void * ctx)251 static void sql_abort_row(void *ctx) {
252 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
253 DBUG_TRACE;
254 pctx->current_col = 0;
255 }
256
sql_get_client_capabilities(void *)257 static ulong sql_get_client_capabilities(void *) {
258 DBUG_TRACE;
259 return 0;
260 }
261
sql_get_null(void * ctx)262 static int sql_get_null(void *ctx) {
263 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
264 DBUG_TRACE;
265 uint row = pctx->num_rows;
266 uint col = pctx->current_col;
267 pctx->current_col++;
268
269 memcpy(pctx->sql_str_value[row][col], "[NULL]", sizeof("[NULL]"));
270 pctx->sql_str_len[row][col] = sizeof("[NULL]") - 1;
271
272 return false;
273 }
274
sql_get_integer(void * ctx,longlong value)275 static int sql_get_integer(void *ctx, longlong value) {
276 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
277 DBUG_TRACE;
278 uint row = pctx->num_rows;
279 uint col = pctx->current_col;
280 pctx->current_col++;
281
282 size_t len = snprintf(pctx->sql_str_value[row][col],
283 sizeof(pctx->sql_str_value[row][col]), "%lld", value);
284 pctx->sql_str_len[row][col] = len;
285 pctx->sql_int_value[row][col] = value;
286
287 return false;
288 }
289
sql_get_longlong(void * ctx,longlong value,uint is_unsigned)290 static int sql_get_longlong(void *ctx, longlong value, uint is_unsigned) {
291 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
292 DBUG_TRACE;
293 uint row = pctx->num_rows;
294 uint col = pctx->current_col;
295 pctx->current_col++;
296
297 size_t len = snprintf(pctx->sql_str_value[row][col],
298 sizeof(pctx->sql_str_value[row][col]),
299 is_unsigned ? "%llu" : "%lld", value);
300
301 pctx->sql_str_len[row][col] = len;
302 pctx->sql_longlong_value[row][col] = value;
303 pctx->sql_is_unsigned[row][col] = is_unsigned;
304
305 return false;
306 }
307
sql_get_decimal(void * ctx,const decimal_t * value)308 static int sql_get_decimal(void *ctx, const decimal_t *value) {
309 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
310 DBUG_TRACE;
311 uint row = pctx->num_rows;
312 uint col = pctx->current_col;
313 pctx->current_col++;
314
315 size_t len = snprintf(pctx->sql_str_value[row][col],
316 sizeof(pctx->sql_str_value[row][col]),
317 "%s%d.%d(%d)[%s]", value->sign ? "+" : "-", value->intg,
318 value->frac, value->len, (char *)value->buf);
319 pctx->sql_str_len[row][col] = len;
320 pctx->sql_decimal_value[row][col].intg = value->intg;
321 pctx->sql_decimal_value[row][col].frac = value->frac;
322 pctx->sql_decimal_value[row][col].len = value->len;
323 pctx->sql_decimal_value[row][col].sign = value->sign;
324 memset((void *)pctx->sql_decimal_value[row][col].buf, '\0', (int)value->len);
325 memcpy((void *)pctx->sql_decimal_value[row][col].buf, (void *)value->buf,
326 (int)value->len);
327
328 return false;
329 }
330
sql_get_double(void * ctx,double value,uint32 decimals)331 static int sql_get_double(void *ctx, double value, uint32 decimals) {
332 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
333 DBUG_TRACE;
334 uint row = pctx->num_rows;
335 uint col = pctx->current_col;
336 pctx->current_col++;
337
338 size_t len = snprintf(pctx->sql_str_value[row][col],
339 sizeof(pctx->sql_str_value[row][col]), "%3.7g", value);
340
341 pctx->sql_str_len[row][col] = len;
342
343 pctx->sql_double_value[row][col] = value;
344 pctx->sql_double_decimals[row][col] = decimals;
345
346 return false;
347 }
348
sql_get_date(void * ctx,const MYSQL_TIME * value)349 static int sql_get_date(void *ctx, const MYSQL_TIME *value) {
350 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
351 DBUG_TRACE;
352 uint row = pctx->num_rows;
353 uint col = pctx->current_col;
354 pctx->current_col++;
355
356 size_t len =
357 snprintf(pctx->sql_str_value[row][col],
358 sizeof(pctx->sql_str_value[row][col]), "%s%4d-%02d-%02d",
359 value->neg ? "-" : "", value->year, value->month, value->day);
360 pctx->sql_str_len[row][col] = len;
361
362 pctx->sql_date_value[row][col].year = value->year;
363 pctx->sql_date_value[row][col].month = value->month;
364 pctx->sql_date_value[row][col].day = value->day;
365
366 pctx->sql_date_value[row][col].hour = value->hour;
367 pctx->sql_date_value[row][col].minute = value->minute;
368 pctx->sql_date_value[row][col].second = value->second;
369 pctx->sql_date_value[row][col].second_part = value->second_part;
370 pctx->sql_date_value[row][col].neg = value->neg;
371
372 return false;
373 }
374
sql_get_time(void * ctx,const MYSQL_TIME * value,uint decimals)375 static int sql_get_time(void *ctx, const MYSQL_TIME *value, uint decimals) {
376 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
377 DBUG_TRACE;
378 uint row = pctx->num_rows;
379 uint col = pctx->current_col;
380 pctx->current_col++;
381
382 size_t len = snprintf(
383 pctx->sql_str_value[row][col], sizeof(pctx->sql_str_value[row][col]),
384 "%s%02d:%02d:%02d", value->neg ? "-" : "",
385 value->day ? (value->day * 24 + value->hour) : value->hour, value->minute,
386 value->second);
387
388 pctx->sql_str_len[row][col] = len;
389
390 pctx->sql_time_value[row][col].year = value->year;
391 pctx->sql_time_value[row][col].month = value->month;
392 pctx->sql_time_value[row][col].day = value->day;
393
394 pctx->sql_time_value[row][col].hour = value->hour;
395 pctx->sql_time_value[row][col].minute = value->minute;
396 pctx->sql_time_value[row][col].second = value->second;
397 pctx->sql_time_value[row][col].second_part = value->second_part;
398 pctx->sql_time_value[row][col].neg = value->neg;
399 pctx->sql_time_decimals[row][col] = decimals;
400
401 return false;
402 }
403
sql_get_datetime(void * ctx,const MYSQL_TIME * value,uint decimals)404 static int sql_get_datetime(void *ctx, const MYSQL_TIME *value, uint decimals) {
405 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
406 DBUG_TRACE;
407 uint row = pctx->num_rows;
408 uint col = pctx->current_col;
409 pctx->current_col++;
410
411 size_t len = snprintf(
412 pctx->sql_str_value[row][col], sizeof(pctx->sql_str_value[row][col]),
413 "%s%4d-%02d-%02d %02d:%02d:%02d", value->neg ? "-" : "", value->year,
414 value->month, value->day, value->hour, value->minute, value->second);
415
416 pctx->sql_str_len[row][col] = len;
417
418 pctx->sql_datetime_value[row][col].year = value->year;
419 pctx->sql_datetime_value[row][col].month = value->month;
420 pctx->sql_datetime_value[row][col].day = value->day;
421
422 pctx->sql_datetime_value[row][col].hour = value->hour;
423 pctx->sql_datetime_value[row][col].minute = value->minute;
424 pctx->sql_datetime_value[row][col].second = value->second;
425 pctx->sql_datetime_value[row][col].second_part = value->second_part;
426 pctx->sql_datetime_value[row][col].neg = value->neg;
427 pctx->sql_datetime_decimals[row][col] = decimals;
428
429 return false;
430 }
431
sql_get_string(void * ctx,const char * const value,size_t length,const CHARSET_INFO * const)432 static int sql_get_string(void *ctx, const char *const value, size_t length,
433 const CHARSET_INFO *const) {
434 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
435 DBUG_TRACE;
436 uint row = pctx->num_rows;
437 uint col = pctx->current_col;
438 pctx->current_col++;
439
440 strncpy(pctx->sql_str_value[row][col], value, length);
441 pctx->sql_str_len[row][col] = length;
442
443 return false;
444 }
445
sql_handle_ok(void * ctx,uint server_status,uint statement_warn_count,ulonglong affected_rows,ulonglong last_insert_id,const char * const message)446 static void sql_handle_ok(void *ctx, uint server_status,
447 uint statement_warn_count, ulonglong affected_rows,
448 ulonglong last_insert_id, const char *const message) {
449 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
450 DBUG_TRACE;
451 /* This could be an EOF */
452 if (!pctx->num_cols) pctx->num_rows = 0;
453 pctx->server_status = server_status;
454 pctx->warn_count = statement_warn_count;
455 pctx->affected_rows = affected_rows;
456 pctx->last_insert_id = last_insert_id;
457 if (message) strncpy(pctx->message, message, sizeof(pctx->message) - 1);
458 pctx->message[sizeof(pctx->message) - 1] = '\0';
459 }
460
sql_handle_error(void * ctx,uint sql_errno,const char * const err_msg,const char * const sqlstate)461 static void sql_handle_error(void *ctx, uint sql_errno,
462 const char *const err_msg,
463 const char *const sqlstate) {
464 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
465 DBUG_TRACE;
466 pctx->sql_errno = sql_errno;
467 if (pctx->sql_errno) {
468 strcpy(pctx->err_msg, err_msg);
469 strcpy(pctx->sqlstate, sqlstate);
470 }
471 pctx->num_rows = 0;
472 }
473
sql_shutdown(void *,int)474 static void sql_shutdown(void *, int) { DBUG_TRACE; }
475
476 const struct st_command_service_cbs sql_cbs = {
477 sql_start_result_metadata,
478 sql_field_metadata,
479 sql_end_result_metadata,
480 sql_start_row,
481 sql_end_row,
482 sql_abort_row,
483 sql_get_client_capabilities,
484 sql_get_null,
485 sql_get_integer,
486 sql_get_longlong,
487 sql_get_decimal,
488 sql_get_double,
489 sql_get_date,
490 sql_get_time,
491 sql_get_datetime,
492 sql_get_string,
493 sql_handle_ok,
494 sql_handle_error,
495 sql_shutdown,
496 };
497
get_data_str(void * ctx)498 static void get_data_str(void *ctx) {
499 char buffer[STRING_BUFFER_SIZE];
500 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
501
502 /* get values */
503 if ((pctx->num_rows > 0) && (pctx->num_cols > 0)) {
504 for (uint col_count = 0; col_count < pctx->num_cols; col_count++) {
505 WRITE_VAL("%s ", pctx->sql_field[col_count].col_name);
506 }
507 WRITE_STR("\n");
508
509 for (uint row_count = 0; row_count < pctx->num_rows; row_count++) {
510 for (uint col_count = 0; col_count < pctx->num_cols; col_count++) {
511 WRITE_VAL("%s ", pctx->sql_str_value[row_count][col_count]);
512 }
513 WRITE_STR("\n");
514 }
515 WRITE_STR("\n");
516
517 /* Metadata */
518 WRITE_VAL("num_cols : %d\n", pctx->num_cols);
519 WRITE_VAL("nb rows : %d\n", pctx->num_rows);
520 }
521 }
522
handle_error(void * ctx)523 static void handle_error(void *ctx) {
524 char buffer[STRING_BUFFER_SIZE];
525 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
526 /* handle_ok/error */
527 WRITE_VAL("error : %d\n", pctx->sql_errno);
528 WRITE_VAL("error msg : %s\n", pctx->err_msg);
529 }
530
531 #define EXEC_TEST_CMD(s, q, p, ctx) \
532 exec_test_cmd((s), (q), (p), (ctx), false, __FUNCTION__, __LINE__)
533 #define EXEC_TEST_CMD_EX(s, q, p, ctx, err) \
534 exec_test_cmd((s), (q), (p), (ctx), (err), __FUNCTION__, __LINE__)
535
exec_test_cmd(MYSQL_SESSION session,const char * query,void * p MY_ATTRIBUTE ((unused)),void * ctx,bool expect_error,const char * func,uint line)536 static void exec_test_cmd(MYSQL_SESSION session, const char *query,
537 void *p MY_ATTRIBUTE((unused)), void *ctx,
538 bool expect_error, const char *func, uint line) {
539 char buffer[STRING_BUFFER_SIZE];
540 struct st_plugin_ctx *pctx = (struct st_plugin_ctx *)ctx;
541 pctx->reset();
542 cmd.com_query.query = query;
543 cmd.com_query.length = strlen(cmd.com_query.query);
544 WRITE_VAL("%s\n", query);
545 int fail = command_service_run_command(session, COM_QUERY, &cmd,
546 &my_charset_utf8_general_ci, &sql_cbs,
547 CS_TEXT_REPRESENTATION, ctx);
548 if (fail) {
549 srv_session_close(session);
550 if (!expect_error)
551 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG,
552 "test_session_info - ret code : %d at %s:%u", fail, func,
553 line);
554 } else if (pctx->sql_errno)
555 handle_error(ctx);
556 else if (expect_error)
557 LogPluginErrMsg(
558 ERROR_LEVEL, ER_LOG_PRINTF_MSG,
559 "test_session_info - expected error but command did not fail at %s:%u",
560 func, line);
561 else {
562 if (pctx->num_cols) get_data_str(ctx);
563 WRITE_VAL("affected rows : %d\n", pctx->affected_rows);
564 WRITE_VAL("server status : %d\n", pctx->server_status);
565 WRITE_VAL("warn count : %d\n", pctx->warn_count);
566 }
567 WRITE_STR("\n");
568 }
569
test_com_init_db(void * p MY_ATTRIBUTE ((unused)),MYSQL_SESSION st_session,const char * db_name)570 static void test_com_init_db(void *p MY_ATTRIBUTE((unused)),
571 MYSQL_SESSION st_session, const char *db_name) {
572 char buffer[STRING_BUFFER_SIZE];
573 DBUG_TRACE;
574
575 struct st_plugin_ctx *plugin_ctx = new st_plugin_ctx();
576
577 COM_DATA cmd;
578
579 LEX_CSTRING lex_db_name = srv_session_info_get_current_db(st_session);
580 WRITE_VAL("current_db before init_db : %s\n", lex_db_name.str);
581
582 cmd.com_init_db.db_name = db_name;
583 cmd.com_init_db.length = strlen(db_name);
584
585 int fail = command_service_run_command(st_session, COM_INIT_DB, &cmd,
586 &my_charset_utf8_general_ci, &sql_cbs,
587 CS_TEXT_REPRESENTATION, plugin_ctx);
588
589 if (fail) {
590 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG, "run_statement code: %d\n",
591 fail);
592 delete plugin_ctx;
593 return;
594 }
595
596 lex_db_name = srv_session_info_get_current_db(st_session);
597 WRITE_VAL("current_db after init_db : %s\n", lex_db_name.str);
598
599 delete plugin_ctx;
600 }
601
test_sql(void * p)602 static void test_sql(void *p) {
603 char buffer[STRING_BUFFER_SIZE + 1];
604 char buffer_query[STRING_BUFFER_SIZE];
605
606 DBUG_TRACE;
607 MYSQL_SESSION session_1, session_2, session_3;
608 struct st_plugin_ctx *plugin_ctx = new st_plugin_ctx();
609
610 /* Opening session 1 */
611 WRITE_STR("Opening Session 1\n");
612 session_1 = srv_session_open(NULL, plugin_ctx);
613 if (!session_1)
614 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG, "Opening Session 1 failed");
615 else
616 switch_user(session_1, user_privileged);
617
618 /* Opening session 2 */
619 WRITE_STR("Opening Session 2\n");
620 session_2 = srv_session_open(NULL, plugin_ctx);
621 if (!session_2)
622 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG, "Opening Session 2 failed");
623 else
624 switch_user(session_2, user_privileged);
625
626 /* srv_session_info_get_thd and srv_session_info_get_session_id*/
627 /* Session 1 */
628 WRITE_SEP();
629 WRITE_STR(
630 "Session 1 : srv_session_info_get_thd and "
631 "srv_session_info_get_session_id\n");
632 WRITE_SEP();
633 my_thread_id session_1_id = srv_session_info_get_session_id(session_1);
634 my_thread_id session_2_id = srv_session_info_get_session_id(session_2);
635 MYSQL_THD thd = srv_session_info_get_thd(session_1);
636 unsigned long thd_id = thd_get_thread_id(thd);
637 if (thd_id != session_1_id) {
638 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG,
639 "Thread handler id is NOT equal to session id "
640 "srv_session_info_get_session_id(session_1)");
641 return;
642 } else {
643 WRITE_STR(
644 "Thread handler id IS equal to session id returned by "
645 "srv_session_info_get_session_id(Session_1)\n\n");
646 }
647
648 /* Session 2 */
649 WRITE_SEP();
650 WRITE_STR(
651 "Session 2 : srv_session_info_get_thd and "
652 "srv_session_info_get_session_id\n");
653 WRITE_SEP();
654 thd = srv_session_info_get_thd(session_2);
655 thd_id = thd_get_thread_id(thd);
656
657 if (thd_id != session_2_id) {
658 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG,
659 "Thread handler id is NOT equal to session id "
660 "srv_session_info_get_session_id(session_2)");
661 delete plugin_ctx;
662 return;
663 } else {
664 WRITE_STR(
665 "Thread handler id IS equal to session id returned by "
666 "srv_session_info_get_session_id(Session_2)\n\n");
667 }
668
669 /* All information from performance_schema */
670 snprintf(buffer_query, sizeof(buffer_query),
671 "SELECT "
672 "name,type,processlist_id,processlist_user,processlist_host,"
673 "processlist_db,processlist_command,processlist_state,processlist_"
674 "info,`role`,instrumented,history,connection_type FROM "
675 "performance_schema.threads WHERE processlist_id = %u",
676 session_1_id);
677 EXEC_TEST_CMD(session_1, buffer_query, p, plugin_ctx);
678
679 snprintf(buffer_query, sizeof(buffer_query),
680 "SELECT "
681 "name,type,processlist_id,processlist_user,processlist_host,"
682 "processlist_db,processlist_command,processlist_state,processlist_"
683 "info,`role`,instrumented,history,connection_type FROM "
684 "performance_schema.threads WHERE processlist_id = %u",
685 session_2_id);
686 EXEC_TEST_CMD(session_2, buffer_query, p, plugin_ctx);
687
688 /* srv_session_info_get_current_db */
689 /* Session 1 */
690 WRITE_SEP();
691 WRITE_STR("Session 1 : srv_session_info_get_current_db\n");
692 WRITE_SEP();
693 EXEC_TEST_CMD(session_1, "/*Session_1*/ SHOW TABLES LIKE '%slave%'", p,
694 plugin_ctx);
695 test_com_init_db(p, session_1, "mysql");
696 WRITE_STR("\n");
697 EXEC_TEST_CMD(session_1, "/*Session_1*/ SHOW TABLES LIKE '%slave%'", p,
698 plugin_ctx);
699
700 EXEC_TEST_CMD(session_1, "/*Session_1*/ USE information_schema", p,
701 plugin_ctx);
702 LEX_CSTRING db_name = srv_session_info_get_current_db(session_1);
703 WRITE_VAL("current_db after 'USE db_name' command : %s\n\n", db_name.str);
704
705 test_com_init_db(p, session_1, "test");
706 WRITE_STR("\n");
707 EXEC_TEST_CMD(session_1, "/*Session_1*/ SHOW TABLES", p, plugin_ctx);
708 /* Session 2 */
709 WRITE_SEP();
710 WRITE_STR("Session 2 : srv_session_info_get_current_db\n");
711 WRITE_SEP();
712 EXEC_TEST_CMD(session_2, "/*Session_2*/ SHOW TABLES LIKE '%slave%'", p,
713 plugin_ctx);
714 test_com_init_db(p, session_2, "mysql");
715 WRITE_STR("\n");
716 WRITE_STR("Session 2's view\n");
717 EXEC_TEST_CMD(session_2, "/*Session_2*/ SHOW TABLES LIKE '%slave%'", p,
718 plugin_ctx);
719
720 WRITE_STR("Session 2's view\n");
721 EXEC_TEST_CMD(session_2, "/*Session_2*/ USE information_schema", p,
722 plugin_ctx);
723 db_name = srv_session_info_get_current_db(session_2);
724 WRITE_VAL("current_db after 'USE db_name' command : %s\n\n", db_name.str);
725
726 test_com_init_db(p, session_2, "test");
727 WRITE_STR("\n");
728 WRITE_STR("Session 2's view\n");
729 EXEC_TEST_CMD(session_2, "/*Session_2*/ SHOW TABLES", p, plugin_ctx);
730
731 /* srv_session_info_set/get_client_port */
732 /* Session 1 */
733 WRITE_SEP();
734 WRITE_STR("Session 1 : srv_session_info_set/get_client_port\n");
735 WRITE_SEP();
736 WRITE_VAL("Port before srv_session_info_set_client_port : %d\n",
737 srv_session_info_get_client_port(session_1));
738 srv_session_info_set_client_port(session_1, 100);
739 WRITE_VAL("Port after srv_session_info_set_client_port : %d\n\n",
740 srv_session_info_get_client_port(session_1));
741
742 WRITE_STR("Session 1's view\n");
743 EXEC_TEST_CMD(session_1,
744 "/*Session_1*/ SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST "
745 "WHERE info LIKE 'PLUGIN%' ORDER BY id",
746 p, plugin_ctx);
747 WRITE_STR("Session 2's view\n");
748 EXEC_TEST_CMD(session_2,
749 "/*Session_2*/ SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST "
750 "WHERE info LIKE 'PLUGIN%' ORDER BY id",
751 p, plugin_ctx);
752
753 /* Session 2 */
754 WRITE_SEP();
755 WRITE_STR("Session 2 : srv_session_info_set/get_client_port\n");
756 WRITE_SEP();
757 WRITE_VAL("Port before srv_session_info_set_client_port : %d\n",
758 srv_session_info_get_client_port(session_2));
759 srv_session_info_set_client_port(session_2, 200);
760 WRITE_VAL("Port after srv_session_info_set_client_port : %d\n\n",
761 srv_session_info_get_client_port(session_2));
762
763 WRITE_STR("Session 1's view\n");
764 EXEC_TEST_CMD(session_1,
765 "/*Session_1*/ SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST "
766 "WHERE info LIKE 'PLUGIN%' ORDER BY id",
767 p, plugin_ctx);
768 WRITE_STR("Session 2's view\n");
769 EXEC_TEST_CMD(session_2,
770 "/*Session_2*/ SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST "
771 "WHERE info LIKE 'PLUGIN%' ORDER BY id",
772 p, plugin_ctx);
773
774 /* srv_session_info_set_connection_type */
775 /* Session 1 */
776 WRITE_SEP();
777 WRITE_STR("Session 1 : srv_session_info_set_connection_type\n");
778 WRITE_SEP();
779 snprintf(buffer_query, sizeof(buffer_query),
780 "SELECT CONNECTION_TYPE, CONNECTION_TYPE IS NULL FROM "
781 "performance_schema.threads WHERE PROCESSLIST_ID = %u "
782 "/*session_1_id*/",
783 session_1_id);
784 WRITE_STR("Session 1's view\n");
785 EXEC_TEST_CMD(session_1, buffer_query, p, plugin_ctx);
786
787 WRITE_STR("Setting NO_VIO_TYPE on session_1\n");
788 if (0 == srv_session_info_set_connection_type(session_1, NO_VIO_TYPE))
789 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG,
790 "srv_session_info_set_connection_type(NO_VIO_TYPE) "
791 "should fail but did not");
792
793 snprintf(buffer_query, sizeof(buffer_query),
794 "SELECT CONNECTION_TYPE FROM performance_schema.threads WHERE "
795 "PROCESSLIST_ID = %u /*session_1_id*/",
796 session_1_id);
797 WRITE_STR("Session 1's view\n");
798 EXEC_TEST_CMD(session_1, buffer_query, p, plugin_ctx);
799
800 WRITE_STR("Setting VIO_TYPE_TCPIP on session_1\n");
801 srv_session_info_set_connection_type(session_1, VIO_TYPE_TCPIP);
802 snprintf(buffer_query, sizeof(buffer_query),
803 "SELECT CONNECTION_TYPE FROM performance_schema.threads WHERE "
804 "PROCESSLIST_ID = %u /*session_1_id*/",
805 session_1_id);
806 WRITE_STR("Session 1's view\n");
807 EXEC_TEST_CMD(session_1, buffer_query, p, plugin_ctx);
808
809 WRITE_STR("Setting VIO_TYPE_NAMEDPIPE on session_1\n");
810 srv_session_info_set_connection_type(session_1, VIO_TYPE_NAMEDPIPE);
811 snprintf(buffer_query, sizeof(buffer_query),
812 "SELECT CONNECTION_TYPE FROM performance_schema.threads WHERE "
813 "PROCESSLIST_ID = %u /*session_1_id*/",
814 session_1_id);
815 WRITE_STR("Session 1's view\n");
816 EXEC_TEST_CMD(session_1, buffer_query, p, plugin_ctx);
817
818 /* Session 2 */
819 WRITE_SEP();
820 WRITE_STR("Session 2 : srv_session_info_set_connection_type\n");
821 WRITE_SEP();
822 snprintf(buffer_query, sizeof(buffer_query),
823 "SELECT CONNECTION_TYPE FROM performance_schema.threads WHERE "
824 "PROCESSLIST_ID = %u /*session_2_id*/",
825 session_2_id);
826 WRITE_STR("Session 2's view\n");
827 EXEC_TEST_CMD(session_2, buffer_query, p, plugin_ctx);
828
829 /* Now test with SSL/TLS */
830 WRITE_STR("Setting VIO_TYPE_SSL on session_2\n");
831 srv_session_info_set_connection_type(session_2, VIO_TYPE_SSL);
832 /* Don't delete the following. We check if set of type on detached session
833 * will affect PFS. The thread should be SSL */
834 WRITE_STR("Setting VIO_TYPE_TCPIP on session_1\n");
835 srv_session_info_set_connection_type(session_1, VIO_TYPE_TCPIP);
836 snprintf(buffer_query, sizeof(buffer_query),
837 "SELECT CONNECTION_TYPE FROM performance_schema.threads WHERE "
838 "PROCESSLIST_ID = %u /*session_2_id*/",
839 session_2_id);
840 WRITE_STR("Session 2's view\n");
841 EXEC_TEST_CMD(session_2, buffer_query, p, plugin_ctx);
842
843 srv_session_info_set_connection_type(session_2, VIO_TYPE_SHARED_MEMORY);
844 snprintf(buffer_query, sizeof(buffer_query),
845 "SELECT CONNECTION_TYPE FROM performance_schema.threads WHERE "
846 "PROCESSLIST_ID = %u /*session_2_id*/",
847 session_2_id);
848 WRITE_STR("Session 2's view\n");
849 EXEC_TEST_CMD(session_2, buffer_query, p, plugin_ctx);
850
851 /* srv_session_info_killed */
852 /* Session 1 */
853 WRITE_SEP();
854 WRITE_STR("BEFORE kill of Session 1\n");
855 WRITE_SEP();
856 EXEC_TEST_CMD(session_1,
857 "SELECT ID, USER, HOST, DB, COMMAND, INFO FROM "
858 "INFORMATION_SCHEMA.PROCESSLIST WHERE info LIKE 'PLUGIN%' "
859 "ORDER BY id",
860 p, plugin_ctx);
861 WRITE_SEP();
862 WRITE_VAL("srv_session_info_killed(Session_1) : %d\n",
863 srv_session_info_killed(session_1));
864 WRITE_VAL("srv_session_info_killed(Session_2) : %d\n",
865 srv_session_info_killed(session_2));
866
867 WRITE_SEP();
868 WRITE_STR("Killing Session 1\n");
869 snprintf(buffer_query, sizeof(buffer_query),
870 "KILL CONNECTION %u /*session_1_id*/", session_1_id);
871 EXEC_TEST_CMD(session_2, buffer_query, p, plugin_ctx);
872
873 WRITE_SEP();
874 WRITE_STR("AFTER kill of Session 1\n");
875 WRITE_SEP();
876 EXEC_TEST_CMD_EX(session_1,
877 "SELECT ID, USER, HOST, DB, COMMAND, INFO FROM "
878 "INFORMATION_SCHEMA.PROCESSLIST WHERE info LIKE 'PLUGIN%' "
879 "ORDER BY id",
880 p, plugin_ctx, true);
881 session_1 = nullptr; // session_1 is closed in EXEC_TEST_CMD_EX.
882 WRITE_SEP();
883 WRITE_VAL("srv_session_info_killed(Session 1) : %d\n",
884 srv_session_info_killed(session_1));
885 WRITE_VAL("srv_session_info_killed(Session 2) : %d\n",
886 srv_session_info_killed(session_2));
887
888 /* Close session 1 */
889 WRITE_SEP();
890 WRITE_STR("Closing Session 1\n");
891 if (srv_session_close(session_1))
892 WRITE_STR(
893 "Closing Session 1 failed as expected. It was already closed by "
894 "EXEC_TEST_CMD\n");
895
896 WRITE_SEP();
897 WRITE_STR("Get/Set session info with closed session(Session 1)\n");
898 WRITE_SEP();
899
900 db_name = srv_session_info_get_current_db(session_1);
901
902 WRITE_VAL("srv_session_info_get_thd : %d\n",
903 (bool)srv_session_info_get_thd(session_1));
904 WRITE_VAL("srv_session_info_get_session_id : %d\n",
905 srv_session_info_get_session_id(session_1));
906 WRITE_VAL("srv_session_info_set_client_port : %d\n",
907 srv_session_info_set_client_port(session_1, 11111));
908 WRITE_VAL("srv_session_info_get_client_port : %d\n",
909 srv_session_info_get_client_port(session_1));
910 WRITE_VAL("srv_session_info_get_current_db : %s\n", db_name.str);
911 WRITE_VAL(
912 "srv_session_info_set_connection_type : %d\n",
913 srv_session_info_set_connection_type(session_1, VIO_TYPE_SHARED_MEMORY));
914 WRITE_STR("\n");
915
916 WRITE_SEP();
917 EXEC_TEST_CMD_EX(session_1,
918 "SELECT ID, USER, HOST, DB, COMMAND, INFO FROM "
919 "INFORMATION_SCHEMA.PROCESSLIST WHERE info LIKE 'PLUGIN%' "
920 "ORDER BY id",
921 p, plugin_ctx, true);
922 WRITE_SEP();
923 WRITE_STR("Perform KILL QUERY and suicide (KILL CONNECTION) on Session 2\n");
924 WRITE_SEP();
925 snprintf(buffer_query, sizeof(buffer_query), "KILL QUERY %i /*session_2_id*/",
926 session_2_id);
927 WRITE_VAL("%s\n", buffer_query);
928 cmd.com_query.query = buffer_query;
929 cmd.com_query.length = strlen(buffer_query);
930
931 int fail = command_service_run_command(session_2, COM_QUERY, &cmd,
932 &my_charset_utf8_general_ci, &sql_cbs,
933 CS_TEXT_REPRESENTATION, plugin_ctx);
934
935 if (fail) {
936 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG, "run_statement code: %d\n",
937 fail);
938 delete plugin_ctx;
939 return;
940 }
941
942 WRITE_VAL("srv_session_info_killed(Session 2) : %d\n",
943 srv_session_info_killed(session_2));
944
945 snprintf(buffer_query, sizeof(buffer_query),
946 "KILL CONNECTION %i /*session_2_id*/", session_2_id);
947 WRITE_VAL("%s\n", buffer_query);
948 cmd.com_query.query = buffer_query;
949 cmd.com_query.length = strlen(buffer_query);
950
951 fail = command_service_run_command(session_2, COM_QUERY, &cmd,
952 &my_charset_utf8_general_ci, &sql_cbs,
953 CS_TEXT_REPRESENTATION, plugin_ctx);
954
955 if (fail) {
956 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG, "run_statement code: %d\n",
957 fail);
958 delete plugin_ctx;
959 return;
960 }
961
962 WRITE_VAL("srv_session_info_killed(Session 2) : %d\n",
963 srv_session_info_killed(session_2));
964
965 db_name = srv_session_info_get_current_db(session_2);
966
967 WRITE_SEP();
968 WRITE_STR("Get/Set session info with killed session(Session 2)\n");
969 WRITE_SEP();
970 WRITE_VAL("srv_session_info_get_thd : %d\n",
971 (bool)srv_session_info_get_thd(session_2));
972 WRITE_VAL("srv_session_info_get_session_id : %d\n",
973 srv_session_info_get_session_id(session_2));
974 WRITE_VAL("srv_session_info_set_client_port : %d\n",
975 srv_session_info_set_client_port(session_2, 11111));
976 WRITE_VAL("srv_session_info_get_client_port : %d\n",
977 srv_session_info_get_client_port(session_2));
978 WRITE_VAL("srv_session_info_get_current_db : %s\n", db_name.str);
979 WRITE_VAL(
980 "srv_session_info_set_connection_type : %d\n",
981 srv_session_info_set_connection_type(session_2, VIO_TYPE_SHARED_MEMORY));
982 WRITE_STR("\n");
983
984 session_3 = srv_session_open(NULL, plugin_ctx);
985 if (!session_3)
986 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG, "Opening Session 3 failed");
987 else {
988 switch_user(session_3, user_privileged);
989
990 WRITE_SEP();
991 WRITE_STR(
992 "Session 2 got killed but not closed, thus it will appear in the "
993 "processlist as Killed\n");
994 WRITE_SEP();
995 EXEC_TEST_CMD(session_3,
996 "/*Session 3*/SELECT ID, USER, HOST, DB, COMMAND, INFO FROM "
997 "INFORMATION_SCHEMA.PROCESSLIST WHERE info LIKE 'PLUGIN%' "
998 "ORDER BY id",
999 p, plugin_ctx);
1000
1001 WRITE_STR("Closing Session 2\n");
1002 if (srv_session_close(session_2))
1003 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG, "Closing Session 2 failed");
1004
1005 WRITE_STR("Closing Session 3\n");
1006 if (srv_session_close(session_3))
1007 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG, "Closing Session 3 failed");
1008 }
1009
1010 delete plugin_ctx;
1011 }
1012
1013 struct test_thread_context {
1014 my_thread_handle thread;
1015 void *p;
1016 bool thread_finished;
1017 void (*test_function)(void *);
1018 };
1019
test_sql_threaded_wrapper(void * param)1020 static void *test_sql_threaded_wrapper(void *param) {
1021 char buffer[STRING_BUFFER_SIZE];
1022 struct test_thread_context *context = (struct test_thread_context *)param;
1023
1024 WRITE_SEP();
1025 WRITE_STR("init thread\n");
1026 if (srv_session_init_thread(context->p))
1027 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG,
1028 "srv_session_init_thread failed.");
1029
1030 context->test_function(context->p);
1031
1032 WRITE_STR("deinit thread\n");
1033 srv_session_deinit_thread();
1034
1035 context->thread_finished = true;
1036 return nullptr;
1037 }
1038
create_log_file(const char * log_name)1039 static void create_log_file(const char *log_name) {
1040 char filename[FN_REFLEN];
1041
1042 fn_format(filename, log_name, "", ".log",
1043 MY_REPLACE_EXT | MY_UNPACK_FILENAME);
1044 unlink(filename);
1045 outfile = my_open(filename, O_CREAT | O_RDWR, MYF(0));
1046 }
1047
1048 #ifdef HAVE_PSI_INTERFACE
1049 static PSI_thread_key key_thread_session_info = PSI_NOT_INSTRUMENTED;
1050 static PSI_thread_info session_info_threads[] = {
1051 {&key_thread_session_info, "session_info", 0, 0, PSI_DOCUMENT_ME}};
1052 #endif // HAVE_PSI_INTERFACE
1053
test_in_spawned_thread(void * p,void (* test_function)(void *))1054 static void test_in_spawned_thread(void *p, void (*test_function)(void *)) {
1055 my_thread_attr_t attr; /* Thread attributes */
1056 my_thread_attr_init(&attr);
1057 (void)my_thread_attr_setdetachstate(&attr, MY_THREAD_CREATE_JOINABLE);
1058
1059 struct test_thread_context context;
1060
1061 context.p = p;
1062 context.thread_finished = false;
1063 context.test_function = test_function;
1064
1065 /* now create the thread and call test_session within the thread. */
1066 if (mysql_thread_create(key_thread_session_info, &(context.thread), &attr,
1067 test_sql_threaded_wrapper, &context) != 0)
1068 LogPluginErr(ERROR_LEVEL, ER_LOG_PRINTF_MSG,
1069 "Could not create test session thread");
1070 else
1071 my_thread_join(&context.thread, nullptr);
1072 }
1073
test_sql_service_plugin_init(void * p)1074 static int test_sql_service_plugin_init(void *p) {
1075 char buffer[STRING_BUFFER_SIZE];
1076 DBUG_TRACE;
1077 if (init_logging_service_for_plugin(®_srv, &log_bi, &log_bs)) return 1;
1078 LogPluginErr(INFORMATION_LEVEL, ER_LOG_PRINTF_MSG, "Installation.");
1079
1080 create_log_file(log_filename);
1081
1082 #ifdef HAVE_PSI_INTERFACE
1083 const char *const category = "test_service_sql";
1084
1085 mysql_thread_register(category, session_info_threads,
1086 static_cast<int>(array_elements(session_info_threads)));
1087 #endif // HAVE_PSI_INTERFACE
1088
1089 WRITE_SEP();
1090 WRITE_STR("Test in a server thread\n");
1091 test_sql(p);
1092
1093 /* Test in a new thread */
1094 WRITE_STR("Follows threaded run\n");
1095 test_in_spawned_thread(p, test_sql);
1096
1097 my_close(outfile, MYF(0));
1098
1099 return 0;
1100 }
1101
test_sql_service_plugin_deinit(void * p MY_ATTRIBUTE ((unused)))1102 static int test_sql_service_plugin_deinit(void *p MY_ATTRIBUTE((unused))) {
1103 DBUG_TRACE;
1104 LogPluginErr(INFORMATION_LEVEL, ER_LOG_PRINTF_MSG, "Uninstallation.");
1105 deinit_logging_service_for_plugin(®_srv, &log_bi, &log_bs);
1106 return 0;
1107 }
1108
1109 struct st_mysql_daemon test_sql_service_plugin = {
1110 MYSQL_DAEMON_INTERFACE_VERSION};
1111
1112 /*
1113 Plugin library descriptor
1114 */
1115
mysql_declare_plugin(test_daemon)1116 mysql_declare_plugin(test_daemon){
1117 MYSQL_DAEMON_PLUGIN,
1118 &test_sql_service_plugin,
1119 "test_session_info",
1120 PLUGIN_AUTHOR_ORACLE,
1121 "Test session information",
1122 PLUGIN_LICENSE_GPL,
1123 test_sql_service_plugin_init, /* Plugin Init */
1124 nullptr, /* Plugin Check uninstall */
1125 test_sql_service_plugin_deinit, /* Plugin Deinit */
1126 0x0100, /* 1.0 */
1127 nullptr, /* status variables */
1128 nullptr, /* system variables */
1129 nullptr, /* config options */
1130 0, /* flags */
1131 } mysql_declare_plugin_end;
1132