]> TLD Linux GIT Repositories - packages/mysql.git/commitdiff
- cleanup MYSQL_8_0
authorMarcin Krol <hawk@tld-linux.org>
Thu, 20 Feb 2025 22:35:58 +0000 (23:35 +0100)
committerMarcin Krol <hawk@tld-linux.org>
Thu, 20 Feb 2025 22:35:58 +0000 (23:35 +0100)
mysql-readline.patch

index 47071759fdd1619bb6c6915c6abbb33d5ff192d8..fdb01bb9b744eaaf213374a11e8310da00df1bcd 100644 (file)
@@ -32,5489 +32,3 @@ diff -urNpa mysql-8.0.41.orig/client/mysql.cc mysql-8.0.41/client/mysql.cc
  static int not_in_history(const char *line);
  static void initialize_readline(char *name);
  #endif /* HAVE_READLINE */
-diff -urNpa mysql-8.0.41.orig/client/mysql.cc.orig mysql-8.0.41/client/mysql.cc.orig
---- mysql-8.0.41.orig/client/mysql.cc.orig     1970-01-01 01:00:00.000000000 +0100
-+++ mysql-8.0.41/client/mysql.cc.orig  2024-12-16 10:20:55.000000000 +0100
-@@ -0,0 +1,5482 @@
-+/*
-+Copyright (c) 2000, 2024, Oracle and/or its affiliates.
-+
-+This program is free software; you can redistribute it and/or modify
-+it under the terms of the GNU General Public License, version 2.0,
-+as published by the Free Software Foundation.
-+
-+This program is designed to work with certain software (including
-+but not limited to OpenSSL) that is licensed under separate terms,
-+as designated in a particular file or component or in included license
-+documentation.  The authors of MySQL hereby grant you an additional
-+permission to link the program and your derivative works with the
-+separately licensed software that they have either included with
-+the program or referenced in the documentation.
-+
-+This program is distributed in the hope that it will be useful,
-+but WITHOUT ANY WARRANTY; without even the implied warranty of
-+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+GNU General Public License, version 2.0, for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with this program; if not, write to the Free Software
-+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
-+*/
-+
-+// mysql command tool
-+
-+#include "my_config.h"
-+
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <inttypes.h>
-+#include <math.h>
-+#include <signal.h>
-+#include <stdarg.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <sys/types.h>
-+#include <time.h>
-+
-+#include "client/client_priv.h"
-+#include "client/client_query_attributes.h"
-+#include "client/my_readline.h"
-+#include "client/pattern_matcher.h"
-+#include "compression.h"
-+#include "lex_string.h"
-+#include "m_ctype.h"
-+#include "my_compiler.h"
-+#include "my_dbug.h"
-+#include "my_default.h"
-+#include "my_dir.h"
-+#include "my_inttypes.h"
-+#include "my_io.h"
-+#include "my_loglevel.h"
-+#include "my_macros.h"
-+#include "typelib.h"
-+#include "user_registration.h"
-+#include "violite.h"
-+
-+#ifdef HAVE_SYS_IOCTL_H
-+#include <sys/ioctl.h>
-+#endif
-+
-+#if defined(USE_LIBEDIT_INTERFACE)
-+#include <locale.h>
-+#endif
-+
-+#ifdef HAVE_PWD_H
-+#include <pwd.h>
-+#endif
-+
-+#if defined(HAVE_TERM_H)
-+#define NOMACROS  // move() macro interferes with std::move.
-+#include <curses.h>
-+#include <term.h>
-+#endif
-+
-+#if defined(_WIN32)
-+#include <conio.h>
-+
-+// Not using syslog but EventLog on Win32, so a dummy facility is enough.
-+#define LOG_USER 0
-+#else
-+#include <readline.h>
-+#include <syslog.h>
-+
-+#define HAVE_READLINE
-+#define USE_POPEN
-+#endif
-+
-+#include <mysqld_error.h>
-+#include <algorithm>
-+#include <new>
-+
-+#include "sql-common/net_ns.h"
-+#include "sql_common.h"
-+
-+using std::max;
-+using std::min;
-+
-+extern CHARSET_INFO my_charset_utf16le_bin;
-+
-+const char *VER = "14.14";
-+
-+/* Don't try to make a nice table if the data is too big */
-+#define MAX_COLUMN_LENGTH 1024
-+
-+/* Buffer to hold 'version' and 'version_comment' */
-+static char *server_version = nullptr;
-+
-+/* Array of options to pass to libemysqld */
-+#define MAX_SERVER_ARGS 64
-+
-+/* Maximum memory limit that can be claimed by alloca(). */
-+#define MAX_ALLOCA_SIZE 512
-+
-+#include "sql_string.h"
-+
-+#ifdef FN_NO_CASE_SENSE
-+#define cmp_database(cs, A, B) my_strcasecmp((cs), (A), (B))
-+#else
-+#define cmp_database(cs, A, B) strcmp((A), (B))
-+#endif
-+
-+#include "client/completion_hash.h"
-+#include "print_version.h"
-+#include "welcome_copyright_notice.h"  // ORACLE_WELCOME_COPYRIGHT_NOTICE
-+
-+#define PROMPT_CHAR '\\'
-+#define DEFAULT_DELIMITER ";"
-+
-+#define MAX_BATCH_BUFFER_SIZE (1024L * 1024L * 1024L)
-+
-+/** default set of patterns used for history exclusion filter */
-+const static std::string HI_DEFAULTS("*IDENTIFIED*:*PASSWORD*");
-+
-+/** used for matching which history lines to ignore */
-+static Pattern_matcher ignore_matcher;
-+
-+struct STATUS {
-+  int exit_status;
-+  ulong query_start_line;
-+  char *file_name;
-+  LINE_BUFFER *line_buff;
-+  bool batch, add_to_history;
-+};
-+
-+static HashTable ht;
-+static MEM_ROOT argv_alloc{PSI_NOT_INSTRUMENTED, 512};
-+
-+enum enum_info_type { INFO_INFO, INFO_ERROR, INFO_RESULT };
-+typedef enum enum_info_type INFO_TYPE;
-+
-+static MYSQL mysql; /* The connection */
-+static bool ignore_errors = false, wait_flag = false, quick = false,
-+            connected = false, opt_raw_data = false, unbuffered = false,
-+            output_tables = false, opt_rehash = true, skip_updates = false,
-+            safe_updates = false, one_database = false, opt_compress = false,
-+            using_opt_local_infile = false, vertical = false,
-+            line_numbers = true, column_names = true, opt_html = false,
-+            opt_xml = false, opt_nopager = true, opt_outfile = false,
-+            named_cmds = false, opt_nobeep = false, opt_reconnect = true,
-+            default_pager_set = false, opt_sigint_ignore = false,
-+            auto_vertical_output = false, show_warnings = false,
-+            executing_query = false, interrupted_query = false,
-+            ignore_spaces = false, sigint_received = false, opt_syslog = false,
-+            opt_binhex = false;
-+static bool opt_binary_as_hex_set_explicitly = false;
-+static bool debug_info_flag, debug_check_flag;
-+static bool column_types_flag;
-+static bool preserve_comments = false;
-+static ulong opt_max_allowed_packet, opt_net_buffer_length;
-+static uint verbose = 0, opt_silent = 0, opt_mysql_port = 0,
-+            opt_local_infile = 0;
-+static uint opt_enable_cleartext_plugin = 0;
-+static bool using_opt_enable_cleartext_plugin = false;
-+static uint my_end_arg;
-+static char *opt_mysql_unix_port = nullptr;
-+static char *opt_bind_addr = nullptr;
-+static int connect_flag = CLIENT_INTERACTIVE;
-+static bool opt_binary_mode = false;
-+static bool opt_connect_expired_password = false;
-+static char *current_host;
-+static char *dns_srv_name;
-+static char *current_db;
-+static char *current_user = nullptr;
-+static char *current_prompt = nullptr;
-+static char *delimiter_str = nullptr;
-+static char *opt_init_command = nullptr;
-+static const char *default_charset = MYSQL_AUTODETECT_CHARSET_NAME;
-+#ifdef HAVE_READLINE
-+static char *histfile;
-+static char *histfile_tmp;
-+#endif
-+static char *opt_histignore = nullptr;
-+static String glob_buffer, old_buffer;
-+static String processed_prompt;
-+static char *full_username = nullptr, *part_username = nullptr,
-+            *default_prompt = nullptr;
-+static char *current_os_user = nullptr, *current_os_sudouser = nullptr;
-+static int wait_time = 5;
-+static STATUS status;
-+static ulong select_limit, max_join_size, opt_connect_timeout = 0;
-+static char mysql_charsets_dir[FN_REFLEN + 1];
-+static char *opt_plugin_dir = nullptr, *opt_default_auth = nullptr;
-+static char *opt_load_data_local_dir = nullptr;
-+#ifdef HAVE_SETNS
-+static char *opt_network_namespace = nullptr;
-+#endif
-+static const char *xmlmeta[] = {
-+    "&", "&amp;", "<", "&lt;", ">", "&gt;", "\"", "&quot;",
-+    /* Turn \0 into a space. Why not &#0;? That's not valid XML or HTML. */
-+    "\0", " ", nullptr, nullptr};
-+static const char *day_names[] = {"Sun", "Mon", "Tue", "Wed",
-+                                  "Thu", "Fri", "Sat"};
-+static const char *month_names[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-+                                    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-+static char default_pager[FN_REFLEN];
-+static char pager[FN_REFLEN], outfile[FN_REFLEN];
-+static FILE *PAGER, *OUTFILE;
-+static MEM_ROOT hash_mem_root(PSI_NOT_INSTRUMENTED, 16384);
-+static uint prompt_counter;
-+static char delimiter[16] = DEFAULT_DELIMITER;
-+static size_t delimiter_length = 1;
-+unsigned short terminal_width = 80;
-+static uint opt_zstd_compress_level = default_zstd_compression_level;
-+static char *opt_compress_algorithm = nullptr;
-+
-+#if defined(_WIN32)
-+static char *shared_memory_base_name = 0;
-+#endif
-+static uint opt_protocol = 0;
-+static const CHARSET_INFO *charset_info = &my_charset_latin1;
-+
-+static char *opt_fido_register_factor = nullptr;
-+static char *opt_oci_config_file = nullptr;
-+static char *opt_authentication_oci_client_config_profile = nullptr;
-+
-+#include "authentication_kerberos_clientopt-vars.h"
-+#include "caching_sha2_passwordopt-vars.h"
-+#include "multi_factor_passwordopt-vars.h"
-+#include "sslopt-vars.h"
-+
-+const char *default_dbug_option = "d:t:o,/tmp/mysql.trace";
-+static void *ssl_session_data = nullptr;
-+
-+/*
-+  completion_hash is an auxiliary feature for mysql client to complete
-+  an object name(db name, table name and field name) automatically.
-+  e.g.
-+  mysql> use my_d
-+  then press <TAB>, it will check the hash and complete the db name
-+  for users.
-+  the result will be:
-+  mysql> use my_dbname
-+
-+  In general, this feature is only on when it is an interactive mysql client.
-+  It is not possible to use it in test case.
-+
-+  For using this feature in test case, we add the option in debug code.
-+*/
-+#ifndef NDEBUG
-+static bool opt_build_completion_hash = false;
-+#endif
-+
-+#ifdef _WIN32
-+/*
-+  A flag that indicates if --execute buffer has already been converted,
-+  to avoid double conversion on reconnect.
-+*/
-+static bool execute_buffer_conversion_done{false};
-+
-+/*
-+  my_win_is_console(...) is quite slow.
-+  We cache my_win_is_console() results for stdout and stderr.
-+  Any other output files, except stdout and stderr,
-+  cannot be Windows console.
-+  Note, if mysql.exe is executed from a service, its _fileno(stdout) is -1,
-+  so shift (1 << -1) can return implementation defined result.
-+  This corner case is taken into account, as the shift result
-+  will be multiplied to 0 and we'll get 0 as a result.
-+  The same is true for stderr.
-+*/
-+static uint win_is_console_cache =
-+    ((my_win_is_console(stdout)) * (1 << _fileno(stdout))) |
-+    ((my_win_is_console(stderr)) * (1 << _fileno(stderr)));
-+
-+static inline bool my_win_is_console_cached(FILE *file) {
-+  return win_is_console_cache & (1 << _fileno(file));
-+}
-+#endif /* _WIN32 */
-+
-+/* Various printing flags */
-+#define MY_PRINT_ESC_0 1 /* Replace 0x00 bytes to "\0"              */
-+#define MY_PRINT_SPS_0 2 /* Replace 0x00 bytes to space             */
-+#define MY_PRINT_XML 4   /* Encode XML entities                     */
-+#define MY_PRINT_MB 8    /* Recognize multi-byte characters         */
-+#define MY_PRINT_CTRL 16 /* Replace TAB, NL, CR to "\t", "\n", "\r" */
-+
-+void tee_write(FILE *file, const char *s, size_t slen, int flags);
-+void tee_fprintf(FILE *file, const char *fmt, ...)
-+    MY_ATTRIBUTE((format(printf, 2, 3)));
-+void tee_fputs(const char *s, FILE *file);
-+void tee_puts(const char *s, FILE *file);
-+void tee_putc(int c, FILE *file);
-+static void tee_print_sized_data(const char *, unsigned int, unsigned int,
-+                                 bool);
-+/* The names of functions that actually do the manipulation. */
-+static int get_options(int argc, char **argv);
-+extern "C" bool get_one_option(int optid, const struct my_option *opt,
-+                               char *argument);
-+static int com_quit(String *str, char *), com_go(String *str, char *),
-+    com_ego(String *str, char *), com_print(String *str, char *),
-+    com_help(String *str, char *), com_clear(String *str, char *),
-+    com_connect(String *str, char *), com_status(String *str, char *),
-+    com_use(String *str, char *), com_source(String *str, char *),
-+    com_rehash(String *str, char *), com_tee(String *str, char *),
-+    com_notee(String *str, char *), com_charset(String *str, char *),
-+    com_prompt(String *str, char *), com_delimiter(String *str, char *),
-+    com_warnings(String *str, char *), com_nowarnings(String *str, char *),
-+    com_resetconnection(String *str, char *),
-+    com_query_attributes(String *str, char *),
-+    com_ssl_session_data_print(String *str, char *);
-+static int com_shell(String *str, char *);
-+
-+#ifdef USE_POPEN
-+static int com_nopager(String *str, char *), com_pager(String *str, char *),
-+    com_edit(String *str, char *);
-+#endif
-+
-+static int read_and_execute(bool interactive);
-+static bool init_connection_options(MYSQL *mysql);
-+static int sql_connect(char *host, char *database, char *user, uint silent);
-+static const char *server_version_string(MYSQL *mysql);
-+static int put_info(const char *str, INFO_TYPE info, uint error = 0,
-+                    const char *sql_state = nullptr);
-+static int put_error(MYSQL *mysql);
-+static void put_error_if_any(MYSQL *mysql);
-+static void safe_put_field(const char *pos, ulong length);
-+static void xmlencode_print(const char *src, uint length);
-+static void init_pager();
-+static void end_pager();
-+static void init_tee(const char *);
-+static void end_tee();
-+static const char *construct_prompt();
-+static inline void reset_prompt(char *in_string, bool *ml_comment);
-+static char *get_arg(char *line, bool get_next_arg);
-+static void init_username();
-+static void add_int_to_prompt(int toadd);
-+static int get_result_width(MYSQL_RES *res);
-+static int get_field_disp_length(MYSQL_FIELD *field);
-+static int normalize_dbname(const char *line, char *buff, uint buff_size);
-+static int get_quote_count(const char *line);
-+
-+static void add_filtered_history(const char *string);
-+static void add_syslog(const char *buffer); /* for syslog */
-+static void fix_line(String *buffer);
-+
-+static void get_current_os_user();
-+static void get_current_os_sudouser();
-+
-+/* A structure which contains information on the commands this program
-+   can understand. */
-+
-+typedef struct {
-+  const char *name;                 /* User printable name of the function. */
-+  char cmd_char;                    /* mysql command character. NULL if none */
-+  int (*func)(String *str, char *); /* Function to call to do the job. */
-+  bool takes_params;                /* Max parameters for command */
-+  const char *doc;                  /* Documentation for this function.  */
-+} COMMANDS;
-+
-+static COMMANDS commands[] = {
-+    {"?", '?', com_help, true, "Synonym for `help'."},
-+    {"clear", 'c', com_clear, false, "Clear the current input statement."},
-+    {"connect", 'r', com_connect, true,
-+     "Reconnect to the server. Optional arguments are db and host."},
-+    {"delimiter", 'd', com_delimiter, true, "Set statement delimiter."},
-+#ifdef USE_POPEN
-+    {"edit", 'e', com_edit, false, "Edit command with $EDITOR."},
-+#endif
-+    {"ego", 'G', com_ego, false,
-+     "Send command to mysql server, display result vertically."},
-+    {"exit", 'q', com_quit, false, "Exit mysql. Same as quit."},
-+    {"go", 'g', com_go, false, "Send command to mysql server."},
-+    {"help", 'h', com_help, true, "Display this help."},
-+#ifdef USE_POPEN
-+    {"nopager", 'n', com_nopager, false, "Disable pager, print to stdout."},
-+#endif
-+    {"notee", 't', com_notee, false, "Don't write into outfile."},
-+#ifdef USE_POPEN
-+    {"pager", 'P', com_pager, true,
-+     "Set PAGER [to_pager]. Print the query results via PAGER."},
-+#endif
-+    {"print", 'p', com_print, false, "Print current command."},
-+    {"prompt", 'R', com_prompt, true, "Change your mysql prompt."},
-+    {"quit", 'q', com_quit, false, "Quit mysql."},
-+    {"rehash", '#', com_rehash, false, "Rebuild completion hash."},
-+    {"source", '.', com_source, true,
-+     "Execute an SQL script file. Takes a file name as an argument."},
-+    {"status", 's', com_status, false,
-+     "Get status information from the server."},
-+    {"system", '!', com_shell, true,
-+     "Execute a system shell command, if enabled"},
-+    {"tee", 'T', com_tee, true,
-+     "Set outfile [to_outfile]. Append everything into given outfile."},
-+    {"use", 'u', com_use, true,
-+     "Use another database. Takes database name as argument."},
-+    {"charset", 'C', com_charset, true,
-+     "Switch to another charset. Might be needed for processing binlog with "
-+     "multi-byte charsets."},
-+    {"warnings", 'W', com_warnings, false,
-+     "Show warnings after every statement."},
-+    {"nowarning", 'w', com_nowarnings, false,
-+     "Don't show warnings after every statement."},
-+    {"resetconnection", 'x', com_resetconnection, false,
-+     "Clean session context."},
-+    {"query_attributes", 0, com_query_attributes, true,
-+     "Sets string parameters (name1 value1 name2 value2 ...) for the next "
-+     "query to pick up."},
-+    {"ssl_session_data_print", 0, com_ssl_session_data_print, true,
-+     "Serializes the current SSL session data to stdout or file"},
-+    /* Get bash-like expansion for some commands */
-+    {"create table", 0, nullptr, false, ""},
-+    {"create database", 0, nullptr, false, ""},
-+    {"show databases", 0, nullptr, false, ""},
-+    {"show fields from", 0, nullptr, false, ""},
-+    {"show keys from", 0, nullptr, false, ""},
-+    {"show tables", 0, nullptr, false, ""},
-+    {"load data from", 0, nullptr, false, ""},
-+    {"alter table", 0, nullptr, false, ""},
-+    {"set option", 0, nullptr, false, ""},
-+    {"lock tables", 0, nullptr, false, ""},
-+    {"unlock tables", 0, nullptr, false, ""},
-+    /* generated 2006-12-28.  Refresh occasionally from lexer. */
-+    {"ACTION", 0, nullptr, false, ""},
-+    {"ADD", 0, nullptr, false, ""},
-+    {"AFTER", 0, nullptr, false, ""},
-+    {"AGAINST", 0, nullptr, false, ""},
-+    {"AGGREGATE", 0, nullptr, false, ""},
-+    {"ALL", 0, nullptr, false, ""},
-+    {"ALGORITHM", 0, nullptr, false, ""},
-+    {"ALTER", 0, nullptr, false, ""},
-+    {"ANALYZE", 0, nullptr, false, ""},
-+    {"AND", 0, nullptr, false, ""},
-+    {"ANY", 0, nullptr, false, ""},
-+    {"AS", 0, nullptr, false, ""},
-+    {"ASC", 0, nullptr, false, ""},
-+    {"ASCII", 0, nullptr, false, ""},
-+    {"ASENSITIVE", 0, nullptr, false, ""},
-+    {"AUTO_INCREMENT", 0, nullptr, false, ""},
-+    {"AVG", 0, nullptr, false, ""},
-+    {"AVG_ROW_LENGTH", 0, nullptr, false, ""},
-+    {"BACKUP", 0, nullptr, false, ""},
-+    {"BDB", 0, nullptr, false, ""},
-+    {"BEFORE", 0, nullptr, false, ""},
-+    {"BEGIN", 0, nullptr, false, ""},
-+    {"BERKELEYDB", 0, nullptr, false, ""},
-+    {"BETWEEN", 0, nullptr, false, ""},
-+    {"BIGINT", 0, nullptr, false, ""},
-+    {"BINARY", 0, nullptr, false, ""},
-+    {"BINLOG", 0, nullptr, false, ""},
-+    {"BIT", 0, nullptr, false, ""},
-+    {"BLOB", 0, nullptr, false, ""},
-+    {"BOOL", 0, nullptr, false, ""},
-+    {"BOOLEAN", 0, nullptr, false, ""},
-+    {"BOTH", 0, nullptr, false, ""},
-+    {"BTREE", 0, nullptr, false, ""},
-+    {"BY", 0, nullptr, false, ""},
-+    {"BYTE", 0, nullptr, false, ""},
-+    {"CACHE", 0, nullptr, false, ""},
-+    {"CALL", 0, nullptr, false, ""},
-+    {"CASCADE", 0, nullptr, false, ""},
-+    {"CASCADED", 0, nullptr, false, ""},
-+    {"CASE", 0, nullptr, false, ""},
-+    {"CHAIN", 0, nullptr, false, ""},
-+    {"CHANGE", 0, nullptr, false, ""},
-+    {"CHANGED", 0, nullptr, false, ""},
-+    {"CHAR", 0, nullptr, false, ""},
-+    {"CHARACTER", 0, nullptr, false, ""},
-+    {"CHARSET", 0, nullptr, false, ""},
-+    {"CHECK", 0, nullptr, false, ""},
-+    {"CHECKSUM", 0, nullptr, false, ""},
-+    {"CIPHER", 0, nullptr, false, ""},
-+    {"CLIENT", 0, nullptr, false, ""},
-+    {"CLOSE", 0, nullptr, false, ""},
-+    {"CODE", 0, nullptr, false, ""},
-+    {"COLLATE", 0, nullptr, false, ""},
-+    {"COLLATION", 0, nullptr, false, ""},
-+    {"COLUMN", 0, nullptr, false, ""},
-+    {"COLUMNS", 0, nullptr, false, ""},
-+    {"COMMENT", 0, nullptr, false, ""},
-+    {"COMMIT", 0, nullptr, false, ""},
-+    {"COMMITTED", 0, nullptr, false, ""},
-+    {"COMPACT", 0, nullptr, false, ""},
-+    {"COMPRESSED", 0, nullptr, false, ""},
-+    {"CONCURRENT", 0, nullptr, false, ""},
-+    {"CONDITION", 0, nullptr, false, ""},
-+    {"CONNECTION", 0, nullptr, false, ""},
-+    {"CONSISTENT", 0, nullptr, false, ""},
-+    {"CONSTRAINT", 0, nullptr, false, ""},
-+    {"CONTAINS", 0, nullptr, false, ""},
-+    {"CONTINUE", 0, nullptr, false, ""},
-+    {"CONVERT", 0, nullptr, false, ""},
-+    {"CREATE", 0, nullptr, false, ""},
-+    {"CROSS", 0, nullptr, false, ""},
-+    {"CUBE", 0, nullptr, false, ""},
-+    {"CURRENT_DATE", 0, nullptr, false, ""},
-+    {"CURRENT_TIME", 0, nullptr, false, ""},
-+    {"CURRENT_TIMESTAMP", 0, nullptr, false, ""},
-+    {"CURRENT_USER", 0, nullptr, false, ""},
-+    {"CURSOR", 0, nullptr, false, ""},
-+    {"DATA", 0, nullptr, false, ""},
-+    {"DATABASE", 0, nullptr, false, ""},
-+    {"DATABASES", 0, nullptr, false, ""},
-+    {"DATE", 0, nullptr, false, ""},
-+    {"DATETIME", 0, nullptr, false, ""},
-+    {"DAY", 0, nullptr, false, ""},
-+    {"DAY_HOUR", 0, nullptr, false, ""},
-+    {"DAY_MICROSECOND", 0, nullptr, false, ""},
-+    {"DAY_MINUTE", 0, nullptr, false, ""},
-+    {"DAY_SECOND", 0, nullptr, false, ""},
-+    {"DEALLOCATE", 0, nullptr, false, ""},
-+    {"DEC", 0, nullptr, false, ""},
-+    {"DECIMAL", 0, nullptr, false, ""},
-+    {"DECLARE", 0, nullptr, false, ""},
-+    {"DEFAULT", 0, nullptr, false, ""},
-+    {"DEFINER", 0, nullptr, false, ""},
-+    {"DELAYED", 0, nullptr, false, ""},
-+    {"DELAY_KEY_WRITE", 0, nullptr, false, ""},
-+    {"DELETE", 0, nullptr, false, ""},
-+    {"DESC", 0, nullptr, false, ""},
-+    {"DESCRIBE", 0, nullptr, false, ""},
-+    {"DETERMINISTIC", 0, nullptr, false, ""},
-+    {"DIRECTORY", 0, nullptr, false, ""},
-+    {"DISABLE", 0, nullptr, false, ""},
-+    {"DISCARD", 0, nullptr, false, ""},
-+    {"DISTINCT", 0, nullptr, false, ""},
-+    {"DISTINCTROW", 0, nullptr, false, ""},
-+    {"DIV", 0, nullptr, false, ""},
-+    {"DO", 0, nullptr, false, ""},
-+    {"DOUBLE", 0, nullptr, false, ""},
-+    {"DROP", 0, nullptr, false, ""},
-+    {"DUAL", 0, nullptr, false, ""},
-+    {"DUMPFILE", 0, nullptr, false, ""},
-+    {"DUPLICATE", 0, nullptr, false, ""},
-+    {"DYNAMIC", 0, nullptr, false, ""},
-+    {"EACH", 0, nullptr, false, ""},
-+    {"ELSE", 0, nullptr, false, ""},
-+    {"ELSEIF", 0, nullptr, false, ""},
-+    {"ENABLE", 0, nullptr, false, ""},
-+    {"ENCLOSED", 0, nullptr, false, ""},
-+    {"END", 0, nullptr, false, ""},
-+    {"ENGINE", 0, nullptr, false, ""},
-+    {"ENGINES", 0, nullptr, false, ""},
-+    {"ENUM", 0, nullptr, false, ""},
-+    {"ERRORS", 0, nullptr, false, ""},
-+    {"ESCAPE", 0, nullptr, false, ""},
-+    {"ESCAPED", 0, nullptr, false, ""},
-+    {"EVENTS", 0, nullptr, false, ""},
-+    {"EXECUTE", 0, nullptr, false, ""},
-+    {"EXISTS", 0, nullptr, false, ""},
-+    {"EXIT", 0, nullptr, false, ""},
-+    {"EXPANSION", 0, nullptr, false, ""},
-+    {"EXPLAIN", 0, nullptr, false, ""},
-+    {"EXTENDED", 0, nullptr, false, ""},
-+    {"FALSE", 0, nullptr, false, ""},
-+    {"FAST", 0, nullptr, false, ""},
-+    {"FETCH", 0, nullptr, false, ""},
-+    {"FIELDS", 0, nullptr, false, ""},
-+    {"FILE", 0, nullptr, false, ""},
-+    {"FIRST", 0, nullptr, false, ""},
-+    {"FIXED", 0, nullptr, false, ""},
-+    {"FLOAT", 0, nullptr, false, ""},
-+    {"FLOAT4", 0, nullptr, false, ""},
-+    {"FLOAT8", 0, nullptr, false, ""},
-+    {"FLUSH", 0, nullptr, false, ""},
-+    {"FOR", 0, nullptr, false, ""},
-+    {"FORCE", 0, nullptr, false, ""},
-+    {"FOREIGN", 0, nullptr, false, ""},
-+    {"FOUND", 0, nullptr, false, ""},
-+    {"FROM", 0, nullptr, false, ""},
-+    {"FULL", 0, nullptr, false, ""},
-+    {"FULLTEXT", 0, nullptr, false, ""},
-+    {"FUNCTION", 0, nullptr, false, ""},
-+    {"GEOMETRY", 0, nullptr, false, ""},
-+    {"GEOMETRYCOLLECTION", 0, nullptr, false, ""},
-+    {"GET_FORMAT", 0, nullptr, false, ""},
-+    {"GLOBAL", 0, nullptr, false, ""},
-+    {"GRANT", 0, nullptr, false, ""},
-+    {"GRANTS", 0, nullptr, false, ""},
-+    {"GROUP", 0, nullptr, false, ""},
-+    {"HANDLER", 0, nullptr, false, ""},
-+    {"HASH", 0, nullptr, false, ""},
-+    {"HAVING", 0, nullptr, false, ""},
-+    {"HELP", 0, nullptr, false, ""},
-+    {"HIGH_PRIORITY", 0, nullptr, false, ""},
-+    {"HOSTS", 0, nullptr, false, ""},
-+    {"HOUR", 0, nullptr, false, ""},
-+    {"HOUR_MICROSECOND", 0, nullptr, false, ""},
-+    {"HOUR_MINUTE", 0, nullptr, false, ""},
-+    {"HOUR_SECOND", 0, nullptr, false, ""},
-+    {"IDENTIFIED", 0, nullptr, false, ""},
-+    {"IF", 0, nullptr, false, ""},
-+    {"IGNORE", 0, nullptr, false, ""},
-+    {"IMPORT", 0, nullptr, false, ""},
-+    {"IN", 0, nullptr, false, ""},
-+    {"INDEX", 0, nullptr, false, ""},
-+    {"INDEXES", 0, nullptr, false, ""},
-+    {"INFILE", 0, nullptr, false, ""},
-+    {"INNER", 0, nullptr, false, ""},
-+    {"INNOBASE", 0, nullptr, false, ""},
-+    {"INNODB", 0, nullptr, false, ""},
-+    {"INOUT", 0, nullptr, false, ""},
-+    {"INSENSITIVE", 0, nullptr, false, ""},
-+    {"INSERT", 0, nullptr, false, ""},
-+    {"INSERT_METHOD", 0, nullptr, false, ""},
-+    {"INT", 0, nullptr, false, ""},
-+    {"INT1", 0, nullptr, false, ""},
-+    {"INT2", 0, nullptr, false, ""},
-+    {"INT3", 0, nullptr, false, ""},
-+    {"INT4", 0, nullptr, false, ""},
-+    {"INT8", 0, nullptr, false, ""},
-+    {"INTEGER", 0, nullptr, false, ""},
-+    {"INTERVAL", 0, nullptr, false, ""},
-+    {"INTO", 0, nullptr, false, ""},
-+    {"IO_THREAD", 0, nullptr, false, ""},
-+    {"IS", 0, nullptr, false, ""},
-+    {"ISOLATION", 0, nullptr, false, ""},
-+    {"ISSUER", 0, nullptr, false, ""},
-+    {"ITERATE", 0, nullptr, false, ""},
-+    {"INVOKER", 0, nullptr, false, ""},
-+    {"JOIN", 0, nullptr, false, ""},
-+    {"KEY", 0, nullptr, false, ""},
-+    {"KEYS", 0, nullptr, false, ""},
-+    {"KILL", 0, nullptr, false, ""},
-+    {"LANGUAGE", 0, nullptr, false, ""},
-+    {"LAST", 0, nullptr, false, ""},
-+    {"LEADING", 0, nullptr, false, ""},
-+    {"LEAVE", 0, nullptr, false, ""},
-+    {"LEAVES", 0, nullptr, false, ""},
-+    {"LEFT", 0, nullptr, false, ""},
-+    {"LEVEL", 0, nullptr, false, ""},
-+    {"LIKE", 0, nullptr, false, ""},
-+    {"LIMIT", 0, nullptr, false, ""},
-+    {"LINES", 0, nullptr, false, ""},
-+    {"LINESTRING", 0, nullptr, false, ""},
-+    {"LOAD", 0, nullptr, false, ""},
-+    {"LOCAL", 0, nullptr, false, ""},
-+    {"LOCALTIME", 0, nullptr, false, ""},
-+    {"LOCALTIMESTAMP", 0, nullptr, false, ""},
-+    {"LOCK", 0, nullptr, false, ""},
-+    {"LOCKS", 0, nullptr, false, ""},
-+    {"LOGS", 0, nullptr, false, ""},
-+    {"LONG", 0, nullptr, false, ""},
-+    {"LONGBLOB", 0, nullptr, false, ""},
-+    {"LONGTEXT", 0, nullptr, false, ""},
-+    {"LOOP", 0, nullptr, false, ""},
-+    {"LOW_PRIORITY", 0, nullptr, false, ""},
-+    {"MASTER", 0, nullptr, false, ""},
-+    {"MASTER_CONNECT_RETRY", 0, nullptr, false, ""},
-+    {"MASTER_HOST", 0, nullptr, false, ""},
-+    {"MASTER_LOG_FILE", 0, nullptr, false, ""},
-+    {"MASTER_LOG_POS", 0, nullptr, false, ""},
-+    {"MASTER_PASSWORD", 0, nullptr, false, ""},
-+    {"MASTER_PORT", 0, nullptr, false, ""},
-+    {"MASTER_SERVER_ID", 0, nullptr, false, ""},
-+    {"MASTER_SSL", 0, nullptr, false, ""},
-+    {"MASTER_SSL_CA", 0, nullptr, false, ""},
-+    {"MASTER_SSL_CAPATH", 0, nullptr, false, ""},
-+    {"MASTER_SSL_CERT", 0, nullptr, false, ""},
-+    {"MASTER_SSL_CIPHER", 0, nullptr, false, ""},
-+    {"MASTER_TLS_VERSION", 0, nullptr, false, ""},
-+    {"MASTER_SSL_KEY", 0, nullptr, false, ""},
-+    {"MASTER_USER", 0, nullptr, false, ""},
-+    {"MATCH", 0, nullptr, false, ""},
-+    {"MAX_CONNECTIONS_PER_HOUR", 0, nullptr, false, ""},
-+    {"MAX_QUERIES_PER_HOUR", 0, nullptr, false, ""},
-+    {"MAX_ROWS", 0, nullptr, false, ""},
-+    {"MAX_UPDATES_PER_HOUR", 0, nullptr, false, ""},
-+    {"MAX_USER_CONNECTIONS", 0, nullptr, false, ""},
-+    {"MEDIUM", 0, nullptr, false, ""},
-+    {"MEDIUMBLOB", 0, nullptr, false, ""},
-+    {"MEDIUMINT", 0, nullptr, false, ""},
-+    {"MEDIUMTEXT", 0, nullptr, false, ""},
-+    {"MERGE", 0, nullptr, false, ""},
-+    {"MICROSECOND", 0, nullptr, false, ""},
-+    {"MIDDLEINT", 0, nullptr, false, ""},
-+    {"MIGRATE", 0, nullptr, false, ""},
-+    {"MINUTE", 0, nullptr, false, ""},
-+    {"MINUTE_MICROSECOND", 0, nullptr, false, ""},
-+    {"MINUTE_SECOND", 0, nullptr, false, ""},
-+    {"MIN_ROWS", 0, nullptr, false, ""},
-+    {"MOD", 0, nullptr, false, ""},
-+    {"MODE", 0, nullptr, false, ""},
-+    {"MODIFIES", 0, nullptr, false, ""},
-+    {"MODIFY", 0, nullptr, false, ""},
-+    {"MONTH", 0, nullptr, false, ""},
-+    {"MULTILINESTRING", 0, nullptr, false, ""},
-+    {"MULTIPOINT", 0, nullptr, false, ""},
-+    {"MULTIPOLYGON", 0, nullptr, false, ""},
-+    {"MUTEX", 0, nullptr, false, ""},
-+    {"NAME", 0, nullptr, false, ""},
-+    {"NAMES", 0, nullptr, false, ""},
-+    {"NATIONAL", 0, nullptr, false, ""},
-+    {"NATURAL", 0, nullptr, false, ""},
-+    {"NDB", 0, nullptr, false, ""},
-+    {"NDBCLUSTER", 0, nullptr, false, ""},
-+    {"NCHAR", 0, nullptr, false, ""},
-+    {"NEW", 0, nullptr, false, ""},
-+    {"NEXT", 0, nullptr, false, ""},
-+    {"NO", 0, nullptr, false, ""},
-+    {"NONE", 0, nullptr, false, ""},
-+    {"NOT", 0, nullptr, false, ""},
-+    {"NO_WRITE_TO_BINLOG", 0, nullptr, false, ""},
-+    {"NULL", 0, nullptr, false, ""},
-+    {"NUMERIC", 0, nullptr, false, ""},
-+    {"NVARCHAR", 0, nullptr, false, ""},
-+    {"OFFSET", 0, nullptr, false, ""},
-+    {"ON", 0, nullptr, false, ""},
-+    {"ONE", 0, nullptr, false, ""},
-+    {"ONE_SHOT", 0, nullptr, false, ""},
-+    {"OPEN", 0, nullptr, false, ""},
-+    {"OPTIMIZE", 0, nullptr, false, ""},
-+    {"OPTION", 0, nullptr, false, ""},
-+    {"OPTIONALLY", 0, nullptr, false, ""},
-+    {"OR", 0, nullptr, false, ""},
-+    {"ORDER", 0, nullptr, false, ""},
-+    {"OUT", 0, nullptr, false, ""},
-+    {"OUTER", 0, nullptr, false, ""},
-+    {"OUTFILE", 0, nullptr, false, ""},
-+    {"PACK_KEYS", 0, nullptr, false, ""},
-+    {"PARTIAL", 0, nullptr, false, ""},
-+    {"PASSWORD", 0, nullptr, false, ""},
-+    {"PHASE", 0, nullptr, false, ""},
-+    {"POINT", 0, nullptr, false, ""},
-+    {"POLYGON", 0, nullptr, false, ""},
-+    {"PRECISION", 0, nullptr, false, ""},
-+    {"PREPARE", 0, nullptr, false, ""},
-+    {"PREV", 0, nullptr, false, ""},
-+    {"PRIMARY", 0, nullptr, false, ""},
-+    {"PRIVILEGES", 0, nullptr, false, ""},
-+    {"PROCEDURE", 0, nullptr, false, ""},
-+    {"PROCESS", 0, nullptr, false, ""},
-+    {"PROCESSLIST", 0, nullptr, false, ""},
-+    {"PURGE", 0, nullptr, false, ""},
-+    {"QUARTER", 0, nullptr, false, ""},
-+    {"QUERY", 0, nullptr, false, ""},
-+    {"QUICK", 0, nullptr, false, ""},
-+    {"READ", 0, nullptr, false, ""},
-+    {"READS", 0, nullptr, false, ""},
-+    {"REAL", 0, nullptr, false, ""},
-+    {"RECOVER", 0, nullptr, false, ""},
-+    {"REDUNDANT", 0, nullptr, false, ""},
-+    {"REFERENCES", 0, nullptr, false, ""},
-+    {"REGEXP", 0, nullptr, false, ""},
-+    {"RELAY_LOG_FILE", 0, nullptr, false, ""},
-+    {"RELAY_LOG_POS", 0, nullptr, false, ""},
-+    {"RELAY_THREAD", 0, nullptr, false, ""},
-+    {"RELEASE", 0, nullptr, false, ""},
-+    {"RELOAD", 0, nullptr, false, ""},
-+    {"RENAME", 0, nullptr, false, ""},
-+    {"REPAIR", 0, nullptr, false, ""},
-+    {"REPEATABLE", 0, nullptr, false, ""},
-+    {"REPLACE", 0, nullptr, false, ""},
-+    {"REPLICATION", 0, nullptr, false, ""},
-+    {"REPEAT", 0, nullptr, false, ""},
-+    {"REQUIRE", 0, nullptr, false, ""},
-+    {"RESET", 0, nullptr, false, ""},
-+    {"RESTORE", 0, nullptr, false, ""},
-+    {"RESTRICT", 0, nullptr, false, ""},
-+    {"RESUME", 0, nullptr, false, ""},
-+    {"RETURN", 0, nullptr, false, ""},
-+    {"RETURNS", 0, nullptr, false, ""},
-+    {"REVOKE", 0, nullptr, false, ""},
-+    {"RIGHT", 0, nullptr, false, ""},
-+    {"RLIKE", 0, nullptr, false, ""},
-+    {"ROLLBACK", 0, nullptr, false, ""},
-+    {"ROLLUP", 0, nullptr, false, ""},
-+    {"ROUTINE", 0, nullptr, false, ""},
-+    {"ROW", 0, nullptr, false, ""},
-+    {"ROWS", 0, nullptr, false, ""},
-+    {"ROW_FORMAT", 0, nullptr, false, ""},
-+    {"RTREE", 0, nullptr, false, ""},
-+    {"SAVEPOINT", 0, nullptr, false, ""},
-+    {"SCHEMA", 0, nullptr, false, ""},
-+    {"SCHEMAS", 0, nullptr, false, ""},
-+    {"SECOND", 0, nullptr, false, ""},
-+    {"SECOND_MICROSECOND", 0, nullptr, false, ""},
-+    {"SECURITY", 0, nullptr, false, ""},
-+    {"SELECT", 0, nullptr, false, ""},
-+    {"SENSITIVE", 0, nullptr, false, ""},
-+    {"SEPARATOR", 0, nullptr, false, ""},
-+    {"SERIAL", 0, nullptr, false, ""},
-+    {"SERIALIZABLE", 0, nullptr, false, ""},
-+    {"SESSION", 0, nullptr, false, ""},
-+    {"SET", 0, nullptr, false, ""},
-+    {"SHARE", 0, nullptr, false, ""},
-+    {"SHOW", 0, nullptr, false, ""},
-+    {"SHUTDOWN", 0, nullptr, false, ""},
-+    {"SIGNED", 0, nullptr, false, ""},
-+    {"SIMPLE", 0, nullptr, false, ""},
-+    {"SLAVE", 0, nullptr, false, ""},
-+    {"SNAPSHOT", 0, nullptr, false, ""},
-+    {"SMALLINT", 0, nullptr, false, ""},
-+    {"SOME", 0, nullptr, false, ""},
-+    {"SONAME", 0, nullptr, false, ""},
-+    {"SOUNDS", 0, nullptr, false, ""},
-+    {"SPATIAL", 0, nullptr, false, ""},
-+    {"SPECIFIC", 0, nullptr, false, ""},
-+    {"SQL", 0, nullptr, false, ""},
-+    {"SQLEXCEPTION", 0, nullptr, false, ""},
-+    {"SQLSTATE", 0, nullptr, false, ""},
-+    {"SQLWARNING", 0, nullptr, false, ""},
-+    {"SQL_BIG_RESULT", 0, nullptr, false, ""},
-+    {"SQL_BUFFER_RESULT", 0, nullptr, false, ""},
-+    {"SQL_CALC_FOUND_ROWS", 0, nullptr, false, ""},
-+    {"SQL_NO_CACHE", 0, nullptr, false, ""},
-+    {"SQL_SMALL_RESULT", 0, nullptr, false, ""},
-+    {"SQL_THREAD", 0, nullptr, false, ""},
-+    {"SQL_TSI_SECOND", 0, nullptr, false, ""},
-+    {"SQL_TSI_MINUTE", 0, nullptr, false, ""},
-+    {"SQL_TSI_HOUR", 0, nullptr, false, ""},
-+    {"SQL_TSI_DAY", 0, nullptr, false, ""},
-+    {"SQL_TSI_WEEK", 0, nullptr, false, ""},
-+    {"SQL_TSI_MONTH", 0, nullptr, false, ""},
-+    {"SQL_TSI_QUARTER", 0, nullptr, false, ""},
-+    {"SQL_TSI_YEAR", 0, nullptr, false, ""},
-+    {"SSL", 0, nullptr, false, ""},
-+    {"START", 0, nullptr, false, ""},
-+    {"STARTING", 0, nullptr, false, ""},
-+    {"STATUS", 0, nullptr, false, ""},
-+    {"STOP", 0, nullptr, false, ""},
-+    {"STORAGE", 0, nullptr, false, ""},
-+    {"STRAIGHT_JOIN", 0, nullptr, false, ""},
-+    {"STRING", 0, nullptr, false, ""},
-+    {"STRIPED", 0, nullptr, false, ""},
-+    {"SUBJECT", 0, nullptr, false, ""},
-+    {"SUPER", 0, nullptr, false, ""},
-+    {"SUSPEND", 0, nullptr, false, ""},
-+    {"TABLE", 0, nullptr, false, ""},
-+    {"TABLES", 0, nullptr, false, ""},
-+    {"TABLESPACE", 0, nullptr, false, ""},
-+    {"TEMPORARY", 0, nullptr, false, ""},
-+    {"TEMPTABLE", 0, nullptr, false, ""},
-+    {"TERMINATED", 0, nullptr, false, ""},
-+    {"TEXT", 0, nullptr, false, ""},
-+    {"THEN", 0, nullptr, false, ""},
-+    {"TIME", 0, nullptr, false, ""},
-+    {"TIMESTAMP", 0, nullptr, false, ""},
-+    {"TIMESTAMPADD", 0, nullptr, false, ""},
-+    {"TIMESTAMPDIFF", 0, nullptr, false, ""},
-+    {"TINYBLOB", 0, nullptr, false, ""},
-+    {"TINYINT", 0, nullptr, false, ""},
-+    {"TINYTEXT", 0, nullptr, false, ""},
-+    {"TO", 0, nullptr, false, ""},
-+    {"TRAILING", 0, nullptr, false, ""},
-+    {"TRANSACTION", 0, nullptr, false, ""},
-+    {"TRIGGER", 0, nullptr, false, ""},
-+    {"TRIGGERS", 0, nullptr, false, ""},
-+    {"TRUE", 0, nullptr, false, ""},
-+    {"TRUNCATE", 0, nullptr, false, ""},
-+    {"TYPE", 0, nullptr, false, ""},
-+    {"TYPES", 0, nullptr, false, ""},
-+    {"UNCOMMITTED", 0, nullptr, false, ""},
-+    {"UNDEFINED", 0, nullptr, false, ""},
-+    {"UNDO", 0, nullptr, false, ""},
-+    {"UNICODE", 0, nullptr, false, ""},
-+    {"UNION", 0, nullptr, false, ""},
-+    {"UNIQUE", 0, nullptr, false, ""},
-+    {"UNKNOWN", 0, nullptr, false, ""},
-+    {"UNLOCK", 0, nullptr, false, ""},
-+    {"UNSIGNED", 0, nullptr, false, ""},
-+    {"UNTIL", 0, nullptr, false, ""},
-+    {"UPDATE", 0, nullptr, false, ""},
-+    {"UPGRADE", 0, nullptr, false, ""},
-+    {"USAGE", 0, nullptr, false, ""},
-+    {"USE", 0, nullptr, false, ""},
-+    {"USER", 0, nullptr, false, ""},
-+    {"USER_RESOURCES", 0, nullptr, false, ""},
-+    {"USE_FRM", 0, nullptr, false, ""},
-+    {"USING", 0, nullptr, false, ""},
-+    {"UTC_DATE", 0, nullptr, false, ""},
-+    {"UTC_TIME", 0, nullptr, false, ""},
-+    {"UTC_TIMESTAMP", 0, nullptr, false, ""},
-+    {"VALUE", 0, nullptr, false, ""},
-+    {"VALUES", 0, nullptr, false, ""},
-+    {"VARBINARY", 0, nullptr, false, ""},
-+    {"VARCHAR", 0, nullptr, false, ""},
-+    {"VARCHARACTER", 0, nullptr, false, ""},
-+    {"VARIABLES", 0, nullptr, false, ""},
-+    {"VARYING", 0, nullptr, false, ""},
-+    {"WARNINGS", 0, nullptr, false, ""},
-+    {"WEEK", 0, nullptr, false, ""},
-+    {"WHEN", 0, nullptr, false, ""},
-+    {"WHERE", 0, nullptr, false, ""},
-+    {"WHILE", 0, nullptr, false, ""},
-+    {"VIEW", 0, nullptr, false, ""},
-+    {"WITH", 0, nullptr, false, ""},
-+    {"WORK", 0, nullptr, false, ""},
-+    {"WRITE", 0, nullptr, false, ""},
-+    {"X509", 0, nullptr, false, ""},
-+    {"XOR", 0, nullptr, false, ""},
-+    {"XA", 0, nullptr, false, ""},
-+    {"YEAR", 0, nullptr, false, ""},
-+    {"YEAR_MONTH", 0, nullptr, false, ""},
-+    {"ZEROFILL", 0, nullptr, false, ""},
-+    {"ABS", 0, nullptr, false, ""},
-+    {"ACOS", 0, nullptr, false, ""},
-+    {"ADDDATE", 0, nullptr, false, ""},
-+    {"ADDTIME", 0, nullptr, false, ""},
-+    {"AES_ENCRYPT", 0, nullptr, false, ""},
-+    {"AES_DECRYPT", 0, nullptr, false, ""},
-+    {"AREA", 0, nullptr, false, ""},
-+    {"ASIN", 0, nullptr, false, ""},
-+    {"ASBINARY", 0, nullptr, false, ""},
-+    {"ASTEXT", 0, nullptr, false, ""},
-+    {"ASWKB", 0, nullptr, false, ""},
-+    {"ASWKT", 0, nullptr, false, ""},
-+    {"ATAN", 0, nullptr, false, ""},
-+    {"ATAN2", 0, nullptr, false, ""},
-+    {"BENCHMARK", 0, nullptr, false, ""},
-+    {"BIN", 0, nullptr, false, ""},
-+    {"BIT_COUNT", 0, nullptr, false, ""},
-+    {"BIT_OR", 0, nullptr, false, ""},
-+    {"BIT_AND", 0, nullptr, false, ""},
-+    {"BIT_XOR", 0, nullptr, false, ""},
-+    {"CAST", 0, nullptr, false, ""},
-+    {"CEIL", 0, nullptr, false, ""},
-+    {"CEILING", 0, nullptr, false, ""},
-+    {"BIT_LENGTH", 0, nullptr, false, ""},
-+    {"CENTROID", 0, nullptr, false, ""},
-+    {"CHAR_LENGTH", 0, nullptr, false, ""},
-+    {"CHARACTER_LENGTH", 0, nullptr, false, ""},
-+    {"COALESCE", 0, nullptr, false, ""},
-+    {"COERCIBILITY", 0, nullptr, false, ""},
-+    {"COMPRESS", 0, nullptr, false, ""},
-+    {"CONCAT", 0, nullptr, false, ""},
-+    {"CONCAT_WS", 0, nullptr, false, ""},
-+    {"CONNECTION_ID", 0, nullptr, false, ""},
-+    {"CONV", 0, nullptr, false, ""},
-+    {"CONVERT_TZ", 0, nullptr, false, ""},
-+    {"COUNT", 0, nullptr, false, ""},
-+    {"COS", 0, nullptr, false, ""},
-+    {"COT", 0, nullptr, false, ""},
-+    {"CRC32", 0, nullptr, false, ""},
-+    {"CROSSES", 0, nullptr, false, ""},
-+    {"CURDATE", 0, nullptr, false, ""},
-+    {"CURTIME", 0, nullptr, false, ""},
-+    {"DATE_ADD", 0, nullptr, false, ""},
-+    {"DATEDIFF", 0, nullptr, false, ""},
-+    {"DATE_FORMAT", 0, nullptr, false, ""},
-+    {"DATE_SUB", 0, nullptr, false, ""},
-+    {"DAYNAME", 0, nullptr, false, ""},
-+    {"DAYOFMONTH", 0, nullptr, false, ""},
-+    {"DAYOFWEEK", 0, nullptr, false, ""},
-+    {"DAYOFYEAR", 0, nullptr, false, ""},
-+    {"DEGREES", 0, nullptr, false, ""},
-+    {"DIMENSION", 0, nullptr, false, ""},
-+    {"DISJOINT", 0, nullptr, false, ""},
-+    {"ELT", 0, nullptr, false, ""},
-+    {"ENDPOINT", 0, nullptr, false, ""},
-+    {"ENVELOPE", 0, nullptr, false, ""},
-+    {"EQUALS", 0, nullptr, false, ""},
-+    {"EXTERIORRING", 0, nullptr, false, ""},
-+    {"EXTRACT", 0, nullptr, false, ""},
-+    {"EXP", 0, nullptr, false, ""},
-+    {"EXPORT_SET", 0, nullptr, false, ""},
-+    {"FIELD", 0, nullptr, false, ""},
-+    {"FIND_IN_SET", 0, nullptr, false, ""},
-+    {"FLOOR", 0, nullptr, false, ""},
-+    {"FORMAT", 0, nullptr, false, ""},
-+    {"FOUND_ROWS", 0, nullptr, false, ""},
-+    {"FROM_DAYS", 0, nullptr, false, ""},
-+    {"FROM_UNIXTIME", 0, nullptr, false, ""},
-+    {"GET_LOCK", 0, nullptr, false, ""},
-+    {"GEOMETRYN", 0, nullptr, false, ""},
-+    {"GEOMETRYTYPE", 0, nullptr, false, ""},
-+    {"GEOMCOLLFROMTEXT", 0, nullptr, false, ""},
-+    {"GEOMCOLLFROMWKB", 0, nullptr, false, ""},
-+    {"GEOMETRYCOLLECTIONFROMTEXT", 0, nullptr, false, ""},
-+    {"GEOMETRYCOLLECTIONFROMWKB", 0, nullptr, false, ""},
-+    {"GEOMETRYFROMTEXT", 0, nullptr, false, ""},
-+    {"GEOMETRYFROMWKB", 0, nullptr, false, ""},
-+    {"GEOMFROMTEXT", 0, nullptr, false, ""},
-+    {"GEOMFROMWKB", 0, nullptr, false, ""},
-+    {"GLENGTH", 0, nullptr, false, ""},
-+    {"GREATEST", 0, nullptr, false, ""},
-+    {"GROUP_CONCAT", 0, nullptr, false, ""},
-+    {"GROUP_UNIQUE_USERS", 0, nullptr, false, ""},
-+    {"HEX", 0, nullptr, false, ""},
-+    {"IFNULL", 0, nullptr, false, ""},
-+    {"INET_ATON", 0, nullptr, false, ""},
-+    {"INET_NTOA", 0, nullptr, false, ""},
-+    {"INSTR", 0, nullptr, false, ""},
-+    {"INTERIORRINGN", 0, nullptr, false, ""},
-+    {"INTERSECTS", 0, nullptr, false, ""},
-+    {"ISCLOSED", 0, nullptr, false, ""},
-+    {"ISEMPTY", 0, nullptr, false, ""},
-+    {"ISNULL", 0, nullptr, false, ""},
-+    {"IS_FREE_LOCK", 0, nullptr, false, ""},
-+    {"IS_USED_LOCK", 0, nullptr, false, ""},
-+    {"JSON_ARRAY_APPEND", 0, nullptr, false, ""},
-+    {"JSON_ARRAY", 0, nullptr, false, ""},
-+    {"JSON_CONTAINS", 0, nullptr, false, ""},
-+    {"JSON_DEPTH", 0, nullptr, false, ""},
-+    {"JSON_EXTRACT", 0, nullptr, false, ""},
-+    {"JSON_INSERT", 0, nullptr, false, ""},
-+    {"JSON_KEYS", 0, nullptr, false, ""},
-+    {"JSON_LENGTH", 0, nullptr, false, ""},
-+    {"JSON_MERGE", 0, nullptr, false, ""},
-+    {"JSON_QUOTE", 0, nullptr, false, ""},
-+    {"JSON_REPLACE", 0, nullptr, false, ""},
-+    {"JSON_ROWOBJECT", 0, nullptr, false, ""},
-+    {"JSON_SEARCH", 0, nullptr, false, ""},
-+    {"JSON_SET", 0, nullptr, false, ""},
-+    {"JSON_TYPE", 0, nullptr, false, ""},
-+    {"JSON_UNQUOTE", 0, nullptr, false, ""},
-+    {"JSON_VALID", 0, nullptr, false, ""},
-+    {"JSON_CONTAINS_PATH", 0, nullptr, false, ""},
-+    {"LAST_INSERT_ID", 0, nullptr, false, ""},
-+    {"ISSIMPLE", 0, nullptr, false, ""},
-+    {"LAST_DAY", 0, nullptr, false, ""},
-+    {"LCASE", 0, nullptr, false, ""},
-+    {"LEAST", 0, nullptr, false, ""},
-+    {"LENGTH", 0, nullptr, false, ""},
-+    {"LN", 0, nullptr, false, ""},
-+    {"LINEFROMTEXT", 0, nullptr, false, ""},
-+    {"LINEFROMWKB", 0, nullptr, false, ""},
-+    {"LINESTRINGFROMTEXT", 0, nullptr, false, ""},
-+    {"LINESTRINGFROMWKB", 0, nullptr, false, ""},
-+    {"LOAD_FILE", 0, nullptr, false, ""},
-+    {"LOCATE", 0, nullptr, false, ""},
-+    {"LOG", 0, nullptr, false, ""},
-+    {"LOG2", 0, nullptr, false, ""},
-+    {"LOG10", 0, nullptr, false, ""},
-+    {"LOWER", 0, nullptr, false, ""},
-+    {"LPAD", 0, nullptr, false, ""},
-+    {"LTRIM", 0, nullptr, false, ""},
-+    {"MAKE_SET", 0, nullptr, false, ""},
-+    {"MAKEDATE", 0, nullptr, false, ""},
-+    {"MAKETIME", 0, nullptr, false, ""},
-+    {"SOURCE_POS_WAIT", 0, nullptr, false, ""},
-+    {"MAX", 0, nullptr, false, ""},
-+    {"MBRCONTAINS", 0, nullptr, false, ""},
-+    {"MBRDISJOINT", 0, nullptr, false, ""},
-+    {"MBREQUAL", 0, nullptr, false, ""},
-+    {"MBRINTERSECTS", 0, nullptr, false, ""},
-+    {"MBROVERLAPS", 0, nullptr, false, ""},
-+    {"MBRTOUCHES", 0, nullptr, false, ""},
-+    {"MBRWITHIN", 0, nullptr, false, ""},
-+    {"MD5", 0, nullptr, false, ""},
-+    {"MID", 0, nullptr, false, ""},
-+    {"MIN", 0, nullptr, false, ""},
-+    {"MLINEFROMTEXT", 0, nullptr, false, ""},
-+    {"MLINEFROMWKB", 0, nullptr, false, ""},
-+    {"MPOINTFROMTEXT", 0, nullptr, false, ""},
-+    {"MPOINTFROMWKB", 0, nullptr, false, ""},
-+    {"MPOLYFROMTEXT", 0, nullptr, false, ""},
-+    {"MPOLYFROMWKB", 0, nullptr, false, ""},
-+    {"MONTHNAME", 0, nullptr, false, ""},
-+    {"MULTILINESTRINGFROMTEXT", 0, nullptr, false, ""},
-+    {"MULTILINESTRINGFROMWKB", 0, nullptr, false, ""},
-+    {"MULTIPOINTFROMTEXT", 0, nullptr, false, ""},
-+    {"MULTIPOINTFROMWKB", 0, nullptr, false, ""},
-+    {"MULTIPOLYGONFROMTEXT", 0, nullptr, false, ""},
-+    {"MULTIPOLYGONFROMWKB", 0, nullptr, false, ""},
-+    {"NAME_CONST", 0, nullptr, false, ""},
-+    {"NOW", 0, nullptr, false, ""},
-+    {"NULLIF", 0, nullptr, false, ""},
-+    {"NUMGEOMETRIES", 0, nullptr, false, ""},
-+    {"NUMINTERIORRINGS", 0, nullptr, false, ""},
-+    {"NUMPOINTS", 0, nullptr, false, ""},
-+    {"OCTET_LENGTH", 0, nullptr, false, ""},
-+    {"OCT", 0, nullptr, false, ""},
-+    {"ORD", 0, nullptr, false, ""},
-+    {"OVERLAPS", 0, nullptr, false, ""},
-+    {"PERIOD_ADD", 0, nullptr, false, ""},
-+    {"PERIOD_DIFF", 0, nullptr, false, ""},
-+    {"PI", 0, nullptr, false, ""},
-+    {"POINTFROMTEXT", 0, nullptr, false, ""},
-+    {"POINTFROMWKB", 0, nullptr, false, ""},
-+    {"POINTN", 0, nullptr, false, ""},
-+    {"POLYFROMTEXT", 0, nullptr, false, ""},
-+    {"POLYFROMWKB", 0, nullptr, false, ""},
-+    {"POLYGONFROMTEXT", 0, nullptr, false, ""},
-+    {"POLYGONFROMWKB", 0, nullptr, false, ""},
-+    {"POSITION", 0, nullptr, false, ""},
-+    {"POW", 0, nullptr, false, ""},
-+    {"POWER", 0, nullptr, false, ""},
-+    {"QUOTE", 0, nullptr, false, ""},
-+    {"RADIANS", 0, nullptr, false, ""},
-+    {"RAND", 0, nullptr, false, ""},
-+    {"RELEASE_LOCK", 0, nullptr, false, ""},
-+    {"REVERSE", 0, nullptr, false, ""},
-+    {"ROUND", 0, nullptr, false, ""},
-+    {"ROW_COUNT", 0, nullptr, false, ""},
-+    {"RPAD", 0, nullptr, false, ""},
-+    {"RTRIM", 0, nullptr, false, ""},
-+    {"SEC_TO_TIME", 0, nullptr, false, ""},
-+    {"SESSION_USER", 0, nullptr, false, ""},
-+    {"SUBDATE", 0, nullptr, false, ""},
-+    {"SIGN", 0, nullptr, false, ""},
-+    {"SIN", 0, nullptr, false, ""},
-+    {"SHA", 0, nullptr, false, ""},
-+    {"SHA1", 0, nullptr, false, ""},
-+    {"SLEEP", 0, nullptr, false, ""},
-+    {"SOUNDEX", 0, nullptr, false, ""},
-+    {"SPACE", 0, nullptr, false, ""},
-+    {"SQRT", 0, nullptr, false, ""},
-+    {"SRID", 0, nullptr, false, ""},
-+    {"STARTPOINT", 0, nullptr, false, ""},
-+    {"STD", 0, nullptr, false, ""},
-+    {"STDDEV", 0, nullptr, false, ""},
-+    {"STDDEV_POP", 0, nullptr, false, ""},
-+    {"STDDEV_SAMP", 0, nullptr, false, ""},
-+    {"STR_TO_DATE", 0, nullptr, false, ""},
-+    {"STRCMP", 0, nullptr, false, ""},
-+    {"SUBSTR", 0, nullptr, false, ""},
-+    {"SUBSTRING", 0, nullptr, false, ""},
-+    {"SUBSTRING_INDEX", 0, nullptr, false, ""},
-+    {"SUBTIME", 0, nullptr, false, ""},
-+    {"SUM", 0, nullptr, false, ""},
-+    {"SYSDATE", 0, nullptr, false, ""},
-+    {"SYSTEM_USER", 0, nullptr, false, ""},
-+    {"TAN", 0, nullptr, false, ""},
-+    {"TIME_FORMAT", 0, nullptr, false, ""},
-+    {"TIME_TO_SEC", 0, nullptr, false, ""},
-+    {"TIMEDIFF", 0, nullptr, false, ""},
-+    {"TO_DAYS", 0, nullptr, false, ""},
-+    {"TOUCHES", 0, nullptr, false, ""},
-+    {"TRIM", 0, nullptr, false, ""},
-+    {"UCASE", 0, nullptr, false, ""},
-+    {"UNCOMPRESS", 0, nullptr, false, ""},
-+    {"UNCOMPRESSED_LENGTH", 0, nullptr, false, ""},
-+    {"UNHEX", 0, nullptr, false, ""},
-+    {"UNIQUE_USERS", 0, nullptr, false, ""},
-+    {"UNIX_TIMESTAMP", 0, nullptr, false, ""},
-+    {"UPPER", 0, nullptr, false, ""},
-+    {"UUID", 0, nullptr, false, ""},
-+    {"VARIANCE", 0, nullptr, false, ""},
-+    {"VAR_POP", 0, nullptr, false, ""},
-+    {"VAR_SAMP", 0, nullptr, false, ""},
-+    {"VERSION", 0, nullptr, false, ""},
-+    {"WEEKDAY", 0, nullptr, false, ""},
-+    {"WEEKOFYEAR", 0, nullptr, false, ""},
-+    {"WITHIN", 0, nullptr, false, ""},
-+    {"X", 0, nullptr, false, ""},
-+    {"Y", 0, nullptr, false, ""},
-+    {"YEARWEEK", 0, nullptr, false, ""},
-+    /* end sentinel */
-+    {(char *)nullptr, 0, nullptr, false, ""}};
-+
-+static const char *load_default_groups[] = {"mysql", "client", nullptr};
-+
-+#ifdef HAVE_READLINE
-+/*
-+ HIST_ENTRY is defined for libedit, but not for the real readline
-+ Need to redefine it for real readline to find it
-+*/
-+#if !defined(HAVE_HIST_ENTRY)
-+typedef struct _hist_entry {
-+  const char *line;
-+  const char *data;
-+} HIST_ENTRY;
-+#endif
-+
-+extern "C" int add_history(const char *command); /* From readline directory */
-+extern "C" int read_history(const char *command);
-+extern "C" int write_history(const char *command);
-+extern "C" HIST_ENTRY *history_get(int num);
-+extern "C" int history_length;
-+static int not_in_history(const char *line);
-+static void initialize_readline(char *name);
-+#endif /* HAVE_READLINE */
-+
-+static COMMANDS *find_command(char *name);
-+static COMMANDS *find_command(char cmd_name);
-+static bool add_line(String &buffer, char *line, size_t line_length,
-+                     char *in_string, bool *ml_comment, bool truncated);
-+static void remove_cntrl(String *buffer);
-+static void print_table_data(MYSQL_RES *result);
-+static void print_table_data_html(MYSQL_RES *result);
-+static void print_table_data_xml(MYSQL_RES *result);
-+static void print_tab_data(MYSQL_RES *result);
-+static void print_table_data_vertically(MYSQL_RES *result);
-+static void print_warnings(void);
-+static ulong start_timer(void);
-+static void end_timer(ulong start_time, char *buff);
-+static void mysql_end_timer(ulong start_time, char *buff);
-+static void nice_time(double sec, char *buff, bool part_second);
-+static void kill_query(const char *reason);
-+extern "C" void mysql_end(int sig);
-+extern "C" void handle_ctrlc_signal(int);
-+extern "C" void handle_quit_signal(int sig);
-+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
-+static void window_resize(int);
-+#endif
-+
-+const char DELIMITER_NAME[] = "delimiter";
-+const uint DELIMITER_NAME_LEN = sizeof(DELIMITER_NAME) - 1;
-+inline bool is_delimiter_command(char *name, ulong len) {
-+  /*
-+    Delimiter command has a parameter, so the length of the whole command
-+    is larger than DELIMITER_NAME_LEN.  We don't care the parameter, so
-+    only name(first DELIMITER_NAME_LEN bytes) is checked.
-+  */
-+  return (len >= DELIMITER_NAME_LEN &&
-+          !my_strnncoll(
-+              charset_info, pointer_cast<uchar *>(name), DELIMITER_NAME_LEN,
-+              pointer_cast<const uchar *>(DELIMITER_NAME), DELIMITER_NAME_LEN));
-+}
-+
-+/**
-+   Get the index of a command in the commands array.
-+
-+   @param cmd_char    Short form command.
-+
-+   @return int
-+     The index of the command is returned if it is found, else -1 is returned.
-+*/
-+inline int get_command_index(char cmd_char) {
-+  /*
-+    All client-specific commands are in the first part of commands array
-+    and have a function to implement it.
-+  */
-+  for (uint i = 0; commands[i].func != nullptr; i++)
-+    if (commands[i].cmd_char == cmd_char) return i;
-+  return -1;
-+}
-+
-+static int delimiter_index = -1;
-+static int charset_index = -1;
-+static bool real_binary_mode = false;
-+
-+#ifdef _WIN32
-+BOOL windows_ctrl_handler(DWORD fdwCtrlType) {
-+  switch (fdwCtrlType) {
-+    case CTRL_C_EVENT:
-+    case CTRL_BREAK_EVENT:
-+      handle_ctrlc_signal(SIGINT);
-+      /* Indicate that signal has beed handled. */
-+      return true;
-+    case CTRL_CLOSE_EVENT:
-+    case CTRL_LOGOFF_EVENT:
-+    case CTRL_SHUTDOWN_EVENT:
-+      handle_quit_signal(SIGINT + 1);
-+  }
-+  /* Pass signal to the next control handler function. */
-+  return false;
-+}
-+#endif
-+
-+int main(int argc, char *argv[]) {
-+  char buff[80];
-+
-+  MY_INIT(argv[0]);
-+  DBUG_TRACE;
-+  DBUG_PROCESS(argv[0]);
-+
-+  charset_index = get_command_index('C');
-+  delimiter_index = get_command_index('d');
-+  delimiter_str = delimiter;
-+  default_prompt = my_strdup(
-+      PSI_NOT_INSTRUMENTED,
-+      getenv("MYSQL_PS1") ? getenv("MYSQL_PS1") : "mysql> ", MYF(MY_WME));
-+  current_prompt = my_strdup(PSI_NOT_INSTRUMENTED, default_prompt, MYF(MY_WME));
-+  prompt_counter = 0;
-+
-+  outfile[0] = 0;              // no (default) outfile
-+  my_stpcpy(pager, "stdout");  // the default, if --pager wasn't given
-+  {
-+    char *tmp = getenv("PAGER");
-+    if (tmp && strlen(tmp)) {
-+      default_pager_set = true;
-+      my_stpcpy(default_pager, tmp);
-+    }
-+  }
-+  if (!isatty(0) || !isatty(1)) {
-+    status.batch = true;
-+    opt_silent = 1;
-+    ignore_errors = false;
-+  } else
-+    status.add_to_history = true;
-+  status.exit_status = 1;
-+
-+  {
-+    /*
-+     The file descriptor-layer may be out-of-sync with the file-number layer,
-+     so we make sure that "stdout" is really open.  If its file is closed then
-+     explicitly close the FD layer.
-+    */
-+    int stdout_fileno_copy;
-+    stdout_fileno_copy = dup(fileno(stdout)); /* Okay if fileno fails. */
-+    if (stdout_fileno_copy == -1) {
-+      fclose(stdout);
-+#ifdef LINUX_ALPINE
-+      // On Alpine linux we need to open a dummy file, so that the first
-+      // call to socket() does not get file number 1
-+      // If socket gets file number 1, then everything printed to stdout
-+      // will be sent back to the server over the socket connection.
-+      fopen("/dev/null", "r");
-+#endif
-+    } else
-+      close(stdout_fileno_copy); /* Clean up dup(). */
-+  }
-+
-+#ifdef _WIN32
-+  /* Convert command line parameters from UTF16LE to UTF8MB4. */
-+  my_win_translate_command_line_args(&my_charset_utf8mb4_bin, &argc, &argv);
-+#endif
-+
-+  my_getopt_use_args_separator = true;
-+  if (load_defaults("my", load_default_groups, &argc, &argv, &argv_alloc)) {
-+    my_end(0);
-+    return EXIT_FAILURE;
-+  }
-+  my_getopt_use_args_separator = false;
-+
-+  get_current_os_user();
-+  get_current_os_sudouser();
-+  if (get_options(argc, (char **)argv)) {
-+    my_end(0);
-+    return EXIT_FAILURE;
-+  }
-+  if (status.batch && !status.line_buff &&
-+      !(status.line_buff = batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin))) {
-+    put_info(
-+        "Can't initialize batch_readline - may be the input source is "
-+        "a directory or a block device.",
-+        INFO_ERROR, 0);
-+    my_end(0);
-+    return EXIT_FAILURE;
-+  }
-+  if (!opt_binary_as_hex_set_explicitly && isatty(0) && isatty(1))
-+    opt_binhex = true;
-+  if (mysql_server_init(0, nullptr, nullptr)) {
-+    put_error(nullptr);
-+    my_end(0);
-+    return EXIT_FAILURE;
-+  }
-+  glob_buffer.mem_realloc((status.batch) ? batch_io_size : 512);
-+  completion_hash_init(&ht, 128);
-+  memset(&mysql, 0, sizeof(mysql));
-+  global_attrs = new client_query_attributes();
-+  if (sql_connect(current_host, current_db, current_user, opt_silent)) {
-+    quick = true;  // Avoid history
-+    status.exit_status = 1;
-+    mysql_end(-1);
-+  }
-+  if (!status.batch) ignore_errors = true;  // Don't abort monitor
-+
-+#ifndef _WIN32
-+  signal(SIGINT, handle_ctrlc_signal);  // Catch SIGINT to clean up
-+  signal(SIGQUIT, mysql_end);           // Catch SIGQUIT to clean up
-+  signal(SIGHUP, handle_quit_signal);   // Catch SIGHUP to clean up
-+#else
-+  SetConsoleCtrlHandler((PHANDLER_ROUTINE)windows_ctrl_handler, true);
-+#endif
-+
-+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
-+  /* Readline will call this if it installs a handler */
-+  signal(SIGWINCH, window_resize);
-+  /* call the SIGWINCH handler to get the default term width */
-+  window_resize(0);
-+#endif
-+
-+  put_info("Welcome to the MySQL monitor.  Commands end with ; or \\g.",
-+           INFO_INFO);
-+  snprintf(glob_buffer.ptr(), glob_buffer.alloced_length(),
-+           "Your MySQL connection id is %lu\nServer version: %s\n",
-+           mysql_thread_id(&mysql), server_version_string(&mysql));
-+  put_info(glob_buffer.ptr(), INFO_INFO);
-+
-+  put_info(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"), INFO_INFO);
-+
-+  if (!status.batch) {
-+    // history ignore patterns are initialized to default values
-+    ignore_matcher.add_patterns(HI_DEFAULTS);
-+
-+    /*
-+      Additional patterns may be supplied using either --histignore option or
-+      MYSQL_HISTIGNORE environment variable. If supplied, they'll get appended
-+      to the default patterns. In case both are specified, pattern(s) supplied
-+      using --histignore option will be used.
-+    */
-+    if (opt_histignore)
-+      ignore_matcher.add_patterns(opt_histignore);
-+    else if (getenv("MYSQL_HISTIGNORE"))
-+      ignore_matcher.add_patterns(getenv("MYSQL_HISTIGNORE"));
-+
-+#ifdef HAVE_READLINE
-+    if (!quick) {
-+      initialize_readline(const_cast<char *>(my_progname));
-+
-+      /* read-history from file, default ~/.mysql_history*/
-+      if (getenv("MYSQL_HISTFILE"))
-+        histfile = my_strdup(PSI_NOT_INSTRUMENTED, getenv("MYSQL_HISTFILE"),
-+                             MYF(MY_WME));
-+      else if (getenv("HOME")) {
-+        histfile = (char *)my_malloc(
-+            PSI_NOT_INSTRUMENTED,
-+            (uint)strlen(getenv("HOME")) + (uint)strlen("/.mysql_history") + 2,
-+            MYF(MY_WME));
-+        if (histfile) sprintf(histfile, "%s/.mysql_history", getenv("HOME"));
-+        char link_name[FN_REFLEN];
-+        if (my_readlink(link_name, histfile, 0) == 0 &&
-+            strncmp(link_name, "/dev/null", 10) == 0) {
-+          /* The .mysql_history file is a symlink to /dev/null, don't use it */
-+          my_free(histfile);
-+          histfile = nullptr;
-+        }
-+      }
-+
-+      /* We used to suggest setting MYSQL_HISTFILE=/dev/null. */
-+      if (histfile && strncmp(histfile, "/dev/null", 10) == 0)
-+        histfile = nullptr;
-+
-+      if (histfile && histfile[0]) {
-+        if (verbose) tee_fprintf(stdout, "Reading history-file %s\n", histfile);
-+        read_history(histfile);
-+        if (!(histfile_tmp =
-+                  (char *)my_malloc(PSI_NOT_INSTRUMENTED,
-+                                    (uint)strlen(histfile) + 5, MYF(MY_WME)))) {
-+          fprintf(stderr, "Couldn't allocate memory for temp histfile!\n");
-+          return EXIT_FAILURE;
-+        }
-+        sprintf(histfile_tmp, "%s.TMP", histfile);
-+      }
-+    }
-+#endif
-+  }
-+
-+  sprintf(
-+      buff, "%s",
-+      "Type 'help;' or '\\h' for help. Type '\\c' to clear the current input "
-+      "statement.\n");
-+  put_info(buff, INFO_INFO);
-+
-+  uint protocol = MYSQL_PROTOCOL_DEFAULT;
-+  uint ssl_mode = 0;
-+  if (!mysql_get_option(&mysql, MYSQL_OPT_PROTOCOL, &protocol) &&
-+      !mysql_get_option(&mysql, MYSQL_OPT_SSL_MODE, &ssl_mode)) {
-+    if (protocol == MYSQL_PROTOCOL_SOCKET && ssl_mode >= SSL_MODE_REQUIRED)
-+      put_info(
-+          "You are enforcing ssl connection via unix socket. Please consider\n"
-+          "switching ssl off as it does not make connection via unix socket\n"
-+          "any more secure.",
-+          INFO_INFO);
-+  }
-+
-+  status.exit_status = read_and_execute(!status.batch);
-+  if (opt_outfile) end_tee();
-+  mysql_end(0);
-+  return 0;  // Keep compiler happy
-+}
-+
-+void mysql_end(int sig) {
-+#ifndef _WIN32
-+  /*
-+    Ignoring SIGQUIT, SIGINT and SIGHUP signals when cleanup process starts.
-+    This will help in resolving the double free issues, which occurs in case
-+    the signal handler function is started in between the clean up function.
-+  */
-+  signal(SIGQUIT, SIG_IGN);
-+  signal(SIGINT, SIG_IGN);
-+  signal(SIGHUP, SIG_IGN);
-+#endif
-+
-+  if (ssl_session_data) mysql_free_ssl_session_data(&mysql, ssl_session_data);
-+  mysql_close(&mysql);
-+#ifdef HAVE_READLINE
-+  if (!status.batch && !quick && histfile && histfile[0]) {
-+    /* write-history */
-+    if (verbose) tee_fprintf(stdout, "Writing history-file %s\n", histfile);
-+    if (!write_history(histfile_tmp))
-+      my_rename(histfile_tmp, histfile, MYF(MY_WME));
-+  }
-+  batch_readline_end(status.line_buff);
-+  completion_hash_free(&ht);
-+  hash_mem_root.Clear();
-+
-+  my_free(histfile);
-+  my_free(histfile_tmp);
-+#endif
-+  my_free(opt_histignore);
-+
-+  my_free(current_os_user);
-+  my_free(current_os_sudouser);
-+
-+  if (opt_syslog) my_closelog();
-+
-+  if (sig >= 0) put_info(sig ? "Aborted" : "Bye", INFO_RESULT);
-+  glob_buffer.mem_free();
-+  old_buffer.mem_free();
-+  processed_prompt.mem_free();
-+  my_free(server_version);
-+  free_passwords();
-+  my_free(opt_mysql_unix_port);
-+  my_free(current_db);
-+  my_free(current_host);
-+  my_free(dns_srv_name);
-+  my_free(current_user);
-+  my_free(full_username);
-+  my_free(part_username);
-+  my_free(default_prompt);
-+#if defined(_WIN32)
-+  my_free(shared_memory_base_name);
-+#endif
-+  my_free(current_prompt);
-+  mysql_server_end();
-+  my_end(my_end_arg);
-+  if (global_attrs != nullptr) {
-+    delete global_attrs;
-+    global_attrs = nullptr;
-+  }
-+  exit(status.exit_status);
-+}
-+
-+/**
-+  SIGINT signal handler.
-+
-+    This function handles SIGINT (Ctrl - C). It sends a 'KILL [QUERY]' command
-+    to the server if a query is currently executing. On Windows, 'Ctrl - Break'
-+    is treated alike.
-+
-+  FIXME: POSIX allows only a very limited set of interactions from signal
-+  handlers, as the main thread could have nearly any state at the time of the
-+  signal and is suspended until the signal handler returns. In particular,
-+  only variables of type sig_atomic_t can be set and tested, and most C library
-+  functions (including malloc()) are banned. Thus, calling kill_query() here
-+  is forbidden and should not be done.
-+*/
-+
-+void handle_ctrlc_signal(int) {
-+  sigint_received = true;
-+
-+  /* Skip rest if --sigint-ignore is used. */
-+  if (opt_sigint_ignore) return;
-+
-+  if (executing_query) kill_query("^C");
-+  /* else, do nothing, just terminate the current line (like /c command). */
-+  return;
-+}
-+
-+/**
-+   Handler to perform a cleanup and quit the program.
-+
-+     This function would send a 'KILL [QUERY]' command to the server if a
-+     query is currently executing and then it invokes mysql_thread_end()/
-+     mysql_end() in order to terminate the mysql client process.
-+
-+  @param sig              Signal number
-+*/
-+
-+void handle_quit_signal(int sig [[maybe_unused]]) {
-+  const char *reason = "Terminal close";
-+
-+  if (!executing_query) {
-+    tee_fprintf(stdout, "%s -- exit!\n", reason);
-+    goto err;
-+  }
-+
-+  kill_query(reason);
-+
-+err:
-+#ifdef _WIN32
-+  /*
-+   When a signal is raised on Windows, the OS creates a new thread to
-+   handle the interrupt. Once that thread completes, the main thread
-+   continues running only to find that it's resources have already been
-+   free'd when the signal handler called mysql_end().
-+  */
-+  mysql_thread_end();
-+  return;
-+#else
-+  mysql_end(sig);
-+#endif
-+}
-+
-+/* Send 'KILL QUERY' command to the server. */
-+static void kill_query(const char *reason) {
-+  char kill_buffer[40];
-+  MYSQL *kill_mysql = nullptr;
-+
-+  kill_mysql = mysql_init(kill_mysql);
-+  init_connection_options(kill_mysql);
-+
-+#ifdef HAVE_SETNS
-+  if (opt_network_namespace && set_network_namespace(opt_network_namespace)) {
-+    goto err;
-+  }
-+#endif
-+
-+  MYSQL *ret;
-+  if (dns_srv_name)
-+    ret = mysql_real_connect_dns_srv(kill_mysql, dns_srv_name, current_user,
-+                                     nullptr, "", 0);
-+  else
-+    ret = mysql_real_connect(kill_mysql, current_host, current_user, nullptr,
-+                             "", opt_mysql_port, opt_mysql_unix_port, 0);
-+  if (!ret) {
-+#ifdef HAVE_SETNS
-+    if (opt_network_namespace) (void)restore_original_network_namespace();
-+#endif
-+    tee_fprintf(stdout,
-+                "%s -- Sorry, cannot connect to the server to kill "
-+                "query, giving up ...\n",
-+                reason);
-+    goto err;
-+  }
-+
-+#ifdef HAVE_SETNS
-+  if (opt_network_namespace && restore_original_network_namespace()) goto err;
-+#endif
-+
-+  interrupted_query = true;
-+
-+  /* mysqld < 5 does not understand KILL QUERY, skip to KILL CONNECTION */
-+  sprintf(kill_buffer, "KILL %s%lu",
-+          (mysql_get_server_version(&mysql) < 50000) ? "" : "QUERY ",
-+          mysql_thread_id(&mysql));
-+
-+  if (verbose)
-+    tee_fprintf(stdout, "%s -- sending \"%s\" to server ...\n", reason,
-+                kill_buffer);
-+  mysql_real_query(kill_mysql, kill_buffer,
-+                   static_cast<ulong>(strlen(kill_buffer)));
-+  tee_fprintf(stdout, "%s -- query aborted\n", reason);
-+
-+err:
-+#ifdef HAVE_SETNS
-+  if (opt_network_namespace) (void)release_network_namespace_resources();
-+#endif
-+  mysql_close(kill_mysql);
-+
-+  return;
-+}
-+
-+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
-+void window_resize(int) {
-+  struct winsize window_size;
-+
-+  if (ioctl(fileno(stdin), TIOCGWINSZ, &window_size) == 0)
-+    terminal_width = window_size.ws_col;
-+}
-+#endif
-+
-+static bool opt_system_command = true;
-+
-+static struct my_option my_long_options[] = {
-+    {"help", '?', "Display this help and exit.", nullptr, nullptr, nullptr,
-+     GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"help", 'I', "Synonym for -?", nullptr, nullptr, nullptr, GET_NO_ARG,
-+     NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"auto-rehash", OPT_AUTO_REHASH,
-+     "Enable automatic rehashing. One doesn't need to use 'rehash' to get "
-+     "table "
-+     "and field completion, but startup and reconnecting may take a longer "
-+     "time. "
-+     "Disable with --disable-auto-rehash.",
-+     &opt_rehash, &opt_rehash, nullptr, GET_BOOL, NO_ARG, 1, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"no-auto-rehash", 'A',
-+     "No automatic rehashing. One has to use 'rehash' to get table and field "
-+     "completion. This gives a quicker start of mysql and disables rehashing "
-+     "on reconnect.",
-+     nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
-+     "Automatically switch to vertical output mode if the result is wider "
-+     "than the terminal width.",
-+     &auto_vertical_output, &auto_vertical_output, nullptr, GET_BOOL, NO_ARG, 0,
-+     0, 0, nullptr, 0, nullptr},
-+    {"batch", 'B',
-+     "Don't use history file. Disable interactive behavior. (Enables "
-+     "--silent.)",
-+     nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"bind-address", 0, "IP address to bind to.", (uchar **)&opt_bind_addr,
-+     (uchar **)&opt_bind_addr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr,
-+     0, nullptr},
-+    {"binary-as-hex", OPT_MYSQL_BINARY_AS_HEX,
-+     "Print binary data as hex. Enabled by default for interactive terminals.",
-+     &opt_binhex, &opt_binhex, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"character-sets-dir", OPT_CHARSETS_DIR,
-+     "Directory for character set files.", &charsets_dir, &charsets_dir,
-+     nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"column-type-info", OPT_COLUMN_TYPES, "Display column type information.",
-+     &column_types_flag, &column_types_flag, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
-+     nullptr, 0, nullptr},
-+    {"comments", 'c',
-+     "Preserve comments. Send comments to the server."
-+     " The default is --skip-comments (discard comments), enable with "
-+     "--comments.",
-+     &preserve_comments, &preserve_comments, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
-+     nullptr, 0, nullptr},
-+    {"compress", 'C', "Use compression in server/client protocol.",
-+     &opt_compress, &opt_compress, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr,
-+     0, nullptr},
-+#ifdef NDEBUG
-+    {"debug", '#', "This is a non-debug version. Catch this and exit.", nullptr,
-+     nullptr, nullptr, GET_DISABLED, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"debug-check", OPT_DEBUG_CHECK,
-+     "This is a non-debug version. Catch this and exit.", nullptr, nullptr,
-+     nullptr, GET_DISABLED, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"debug-info", 'T', "This is a non-debug version. Catch this and exit.",
-+     nullptr, nullptr, nullptr, GET_DISABLED, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+#else
-+    {"debug", '#', "Output debug log.", &default_dbug_option,
-+     &default_dbug_option, nullptr, GET_STR, OPT_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"debug-check", OPT_DEBUG_CHECK,
-+     "Check memory and open file usage at exit.", &debug_check_flag,
-+     &debug_check_flag, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"debug-info", 'T', "Print some debug info at exit.", &debug_info_flag,
-+     &debug_info_flag, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+#endif
-+    {"database", 'D', "Database to use.", &current_db, &current_db, nullptr,
-+     GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"default-character-set", OPT_DEFAULT_CHARSET,
-+     "Set the default character set.", &default_charset, &default_charset,
-+     nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"delimiter", OPT_DELIMITER, "Delimiter to be used.", &delimiter_str,
-+     &delimiter_str, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
-+     "Enable/disable the clear text authentication plugin.",
-+     &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin, nullptr,
-+     GET_BOOL, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"execute", 'e',
-+     "Execute command and quit. (Disables --force and history file.)", nullptr,
-+     nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"vertical", 'E', "Print the output of a query (rows) vertically.",
-+     &vertical, &vertical, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"force", 'f', "Continue even if we get an SQL error.", &ignore_errors,
-+     &ignore_errors, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"histignore", OPT_HISTIGNORE,
-+     "A colon-separated list of patterns to "
-+     "keep statements from getting logged into syslog and mysql history.",
-+     &opt_histignore, &opt_histignore, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0,
-+     0, 0, nullptr, 0, nullptr},
-+    {"named-commands", 'G',
-+     "Enable named commands. Named commands mean this program's internal "
-+     "commands; see mysql> help . When enabled, the named commands can be "
-+     "used from any line of the query, otherwise only from the first line, "
-+     "before an enter. Disable with --disable-named-commands. This option "
-+     "is disabled by default.",
-+     &named_cmds, &named_cmds, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"ignore-spaces", 'i', "Ignore space after function names.", &ignore_spaces,
-+     &ignore_spaces, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"init-command", OPT_INIT_COMMAND,
-+     "SQL Command to execute when connecting to MySQL server. Will "
-+     "automatically be re-executed when reconnecting.",
-+     &opt_init_command, &opt_init_command, nullptr, GET_STR, REQUIRED_ARG, 0, 0,
-+     0, nullptr, 0, nullptr},
-+    {"local-infile", OPT_LOCAL_INFILE, "Enable/disable LOAD DATA LOCAL INFILE.",
-+     &opt_local_infile, &opt_local_infile, nullptr, GET_BOOL, OPT_ARG, 0, 0, 0,
-+     nullptr, 0, nullptr},
-+    {"no-beep", 'b', "Turn off beep on error.", &opt_nobeep, &opt_nobeep,
-+     nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"host", 'h', "Connect to host.", &current_host, &current_host, nullptr,
-+     GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"dns-srv-name", 0, "Connect to a DNS SRV resource", &dns_srv_name,
-+     &dns_srv_name, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"html", 'H', "Produce HTML output.", &opt_html, &opt_html, nullptr,
-+     GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"xml", 'X', "Produce XML output.", &opt_xml, &opt_xml, nullptr, GET_BOOL,
-+     NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"line-numbers", OPT_LINE_NUMBERS, "Write line numbers for errors.",
-+     &line_numbers, &line_numbers, nullptr, GET_BOOL, NO_ARG, 1, 0, 0, nullptr,
-+     0, nullptr},
-+    {"skip-line-numbers", 'L', "Don't write line number for errors.", nullptr,
-+     nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"unbuffered", 'n', "Flush buffer after each query.", &unbuffered,
-+     &unbuffered, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"column-names", OPT_COLUMN_NAMES, "Write column names in results.",
-+     &column_names, &column_names, nullptr, GET_BOOL, NO_ARG, 1, 0, 0, nullptr,
-+     0, nullptr},
-+    {"skip-column-names", 'N', "Don't write column names in results.", nullptr,
-+     nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"sigint-ignore", OPT_SIGINT_IGNORE, "Ignore SIGINT (CTRL-C).",
-+     &opt_sigint_ignore, &opt_sigint_ignore, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
-+     nullptr, 0, nullptr},
-+    {"one-database", 'o',
-+     "Ignore statements except those that occur while the default "
-+     "database is the one named at the command line.",
-+     nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+#ifdef USE_POPEN
-+    {"pager", OPT_PAGER,
-+     "Pager to use to display results. If you don't supply an option, the "
-+     "default pager is taken from your ENV variable PAGER. Valid pagers are "
-+     "less, more, cat [> filename], etc. See interactive help (\\h) also. "
-+     "This option does not work in batch mode. Disable with --disable-pager. "
-+     "This option is disabled by default.",
-+     nullptr, nullptr, nullptr, GET_STR, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+#endif
-+#include "multi_factor_passwordopt-longopts.h"
-+#ifdef _WIN32
-+    {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
-+     NO_ARG, 0, 0, 0, 0, 0, 0},
-+#endif
-+    {"port", 'P',
-+     "Port number to use for connection or 0 for default to, in "
-+     "order of preference, my.cnf, $MYSQL_TCP_PORT, "
-+#if MYSQL_PORT_DEFAULT == 0
-+     "/etc/services, "
-+#endif
-+     "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
-+     &opt_mysql_port, &opt_mysql_port, nullptr, GET_UINT, REQUIRED_ARG, 0, 0, 0,
-+     nullptr, 0, nullptr},
-+    {"prompt", OPT_PROMPT, "Set the mysql prompt to this value.",
-+     &current_prompt, &current_prompt, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0,
-+     0, 0, nullptr, 0, nullptr},
-+    {"protocol", OPT_MYSQL_PROTOCOL,
-+     "The protocol to use for connection (tcp, socket, pipe, memory).", nullptr,
-+     nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"quick", 'q',
-+     "Don't cache result, print it row by row. This may slow down the server "
-+     "if the output is suspended. Doesn't use history file.",
-+     &quick, &quick, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"raw", 'r', "Write fields without conversion. Used with --batch.",
-+     &opt_raw_data, &opt_raw_data, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr,
-+     0, nullptr},
-+    {"reconnect", OPT_RECONNECT,
-+     "Reconnect if the connection is lost. Disable "
-+     "with --disable-reconnect. This option is enabled by default.",
-+     &opt_reconnect, &opt_reconnect, nullptr, GET_BOOL, NO_ARG, 1, 0, 0,
-+     nullptr, 0, nullptr},
-+    {"silent", 's',
-+     "Be more silent. Print results with a tab as separator, "
-+     "each row on new line.",
-+     nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+#if defined(_WIN32)
-+    {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
-+     "Base name of shared memory.", &shared_memory_base_name,
-+     &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0,
-+     0},
-+#endif
-+    {"socket", 'S', "The socket file to use for connection.",
-+     &opt_mysql_unix_port, &opt_mysql_unix_port, nullptr, GET_STR_ALLOC,
-+     REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+#include "caching_sha2_passwordopt-longopts.h"
-+#include "sslopt-longopts.h"
-+
-+    {"table", 't', "Output in table format.", &output_tables, &output_tables,
-+     nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"tee", OPT_TEE,
-+     "Append everything into outfile. See interactive help (\\h) also. "
-+     "Does not work in batch mode. Disable with --disable-tee. "
-+     "This option is disabled by default.",
-+     nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"user", 'u', "User for login if not current user.", &current_user,
-+     &current_user, nullptr, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"safe-updates", 'U', "Only allow UPDATE and DELETE that uses keys.",
-+     &safe_updates, &safe_updates, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr,
-+     0, nullptr},
-+    {"i-am-a-dummy", 'U', "Synonym for option --safe-updates, -U.",
-+     &safe_updates, &safe_updates, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr,
-+     0, nullptr},
-+    {"verbose", 'v', "Write more. (-v -v -v gives the table output format).",
-+     nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"version", 'V', "Output version information and exit.", nullptr, nullptr,
-+     nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"wait", 'w', "Wait and retry if connection is down.", nullptr, nullptr,
-+     nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"connect_timeout", OPT_CONNECT_TIMEOUT,
-+     "Number of seconds before connection timeout.", &opt_connect_timeout,
-+     &opt_connect_timeout, nullptr, GET_ULONG, REQUIRED_ARG, 0, 0, 3600 * 12,
-+     nullptr, 0, nullptr},
-+    {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
-+     "The maximum packet length to send to or receive from server.",
-+     &opt_max_allowed_packet, &opt_max_allowed_packet, nullptr, GET_ULONG,
-+     REQUIRED_ARG, 16 * 1024L * 1024L, 4096,
-+     (longlong)2 * 1024L * 1024L * 1024L, nullptr, 1024, nullptr},
-+    {"net_buffer_length", OPT_NET_BUFFER_LENGTH,
-+     "The buffer size for TCP/IP and socket communication.",
-+     &opt_net_buffer_length, &opt_net_buffer_length, nullptr, GET_ULONG,
-+     REQUIRED_ARG, 16384, 1024, 512 * 1024 * 1024L, nullptr, 1024, nullptr},
-+    {"select_limit", OPT_SELECT_LIMIT,
-+     "Automatic limit for SELECT when using --safe-updates.", &select_limit,
-+     &select_limit, nullptr, GET_ULONG, REQUIRED_ARG, 1000L, 1, ULONG_MAX,
-+     nullptr, 1, nullptr},
-+    {"max_join_size", OPT_MAX_JOIN_SIZE,
-+     "Automatic limit for rows in a join when using --safe-updates.",
-+     &max_join_size, &max_join_size, nullptr, GET_ULONG, REQUIRED_ARG, 1000000L,
-+     1, ULONG_MAX, nullptr, 1, nullptr},
-+    {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
-+     &show_warnings, &show_warnings, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
-+     nullptr, 0, nullptr},
-+    {"syslog", 'j',
-+     "Log filtered interactive commands to syslog. Filtering of "
-+     "commands depends on the patterns supplied via histignore option besides "
-+     "the default patterns.",
-+     nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-+     &opt_plugin_dir, &opt_plugin_dir, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
-+     nullptr, 0, nullptr},
-+    {"default_auth", OPT_DEFAULT_AUTH,
-+     "Default authentication client-side plugin to use.", &opt_default_auth,
-+     &opt_default_auth, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
-+     nullptr},
-+    {"binary-mode", OPT_BINARY_MODE,
-+     "By default, ASCII '\\0' is disallowed and '\\r\\n' is translated to "
-+     "'\\n'. "
-+     "This switch turns off both features, and also turns off parsing of all "
-+     "client"
-+     "commands except \\C and DELIMITER, in non-interactive mode (for input "
-+     "piped to mysql or loaded using the 'source' command). This is necessary "
-+     "when processing output from mysqlbinlog that may contain blobs.",
-+     &opt_binary_mode, &opt_binary_mode, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
-+     nullptr, 0, nullptr},
-+    {"connect-expired-password", 0,
-+     "Notify the server that this client is prepared to handle expired "
-+     "password sandbox mode.",
-+     &opt_connect_expired_password, &opt_connect_expired_password, nullptr,
-+     GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+#ifndef NDEBUG
-+    {"build-completion-hash", 0,
-+     "Build completion hash even when it is in batch mode. It is used for "
-+     "test purpose, so it is just built when DEBUG is on.",
-+     &opt_build_completion_hash, &opt_build_completion_hash, nullptr, GET_BOOL,
-+     NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+#endif
-+#ifdef HAVE_SETNS
-+    {"network-namespace", 0,
-+     "Network namespace to use for connection via tcp with a server.",
-+     &opt_network_namespace, &opt_network_namespace, nullptr, GET_STR,
-+     REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+#endif
-+    {"compression-algorithms", 0,
-+     "Use compression algorithm in server/client protocol. Valid values "
-+     "are any combination of 'zstd','zlib','uncompressed'.",
-+     &opt_compress_algorithm, &opt_compress_algorithm, nullptr, GET_STR,
-+     REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"zstd-compression-level", 0,
-+     "Use this compression level in the client/server protocol, in case "
-+     "--compression-algorithms=zstd. Valid range is between 1 and 22, "
-+     "inclusive. Default is 3.",
-+     &opt_zstd_compress_level, &opt_zstd_compress_level, nullptr, GET_UINT,
-+     REQUIRED_ARG, 3, 1, 22, nullptr, 0, nullptr},
-+    {"load_data_local_dir", OPT_LOAD_DATA_LOCAL_DIR,
-+     "Directory path safe for LOAD DATA LOCAL INFILE to read from.",
-+     &opt_load_data_local_dir, &opt_load_data_local_dir, nullptr, GET_STR,
-+     REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"fido-register-factor", 0,
-+     "Specifies authentication factor, for which registration needs to be "
-+     "done.",
-+     &opt_fido_register_factor, &opt_fido_register_factor, nullptr, GET_STR,
-+     REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"authentication-oci-client-config-profile", 0,
-+     "Specifies the configuration profile whose configuration options are to "
-+     "be read from the OCI configuration file. Default is DEFAULT.",
-+     &opt_authentication_oci_client_config_profile,
-+     &opt_authentication_oci_client_config_profile, nullptr, GET_STR,
-+     REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
-+    {"oci-config-file", 0,
-+     "Specifies the location of the OCI configuration file. Default for Linux "
-+     "is ~/.oci/config and %HOME/.oci/config on Windows.",
-+     &opt_oci_config_file, &opt_oci_config_file, nullptr, GET_STR, REQUIRED_ARG,
-+     0, 0, 0, nullptr, 0, nullptr},
-+#include "authentication_kerberos_clientopt-longopts.h"
-+    {"system-command", 0,
-+     "Enable (by default) or disable the system mysql command.",
-+     &opt_system_command, &opt_system_command, nullptr, GET_BOOL, NO_ARG, 1, 0,
-+     0, nullptr, 0, nullptr},
-+    {nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
-+     0, nullptr, 0, nullptr}};
-+
-+static void usage(int version) {
-+  print_version();
-+
-+  if (version) return;
-+  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
-+  printf("Usage: %s [OPTIONS] [database]\n", my_progname);
-+  my_print_help(my_long_options);
-+  print_defaults("my", load_default_groups);
-+  my_print_variables(my_long_options);
-+}
-+
-+bool get_one_option(int optid, const struct my_option *opt [[maybe_unused]],
-+                    char *argument) {
-+  switch (optid) {
-+    case OPT_CHARSETS_DIR:
-+      strmake(mysql_charsets_dir, argument, sizeof(mysql_charsets_dir) - 1);
-+      charsets_dir = mysql_charsets_dir;
-+      break;
-+    case OPT_DELIMITER:
-+      if (argument == disabled_my_option) {
-+        my_stpcpy(delimiter, DEFAULT_DELIMITER);
-+      } else {
-+        /* Check that delimiter does not contain a backslash */
-+        if (!strstr(argument, "\\")) {
-+          strmake(delimiter, argument, sizeof(delimiter) - 1);
-+        } else {
-+          put_info("DELIMITER cannot contain a backslash character",
-+                   INFO_ERROR);
-+          return false;
-+        }
-+      }
-+      delimiter_length = (uint)strlen(delimiter);
-+      delimiter_str = delimiter;
-+      break;
-+    case OPT_LOCAL_INFILE:
-+      using_opt_local_infile = true;
-+      break;
-+    case OPT_ENABLE_CLEARTEXT_PLUGIN:
-+      using_opt_enable_cleartext_plugin = true;
-+      break;
-+    case OPT_TEE:
-+      if (argument == disabled_my_option) {
-+        if (opt_outfile) end_tee();
-+      } else
-+        init_tee(argument);
-+      break;
-+    case OPT_PAGER:
-+      if (argument == disabled_my_option)
-+        opt_nopager = true;
-+      else {
-+        opt_nopager = false;
-+        if (argument && strlen(argument)) {
-+          default_pager_set = true;
-+          strmake(pager, argument, sizeof(pager) - 1);
-+          my_stpcpy(default_pager, pager);
-+        } else if (default_pager_set)
-+          my_stpcpy(pager, default_pager);
-+        else
-+          opt_nopager = true;
-+      }
-+      break;
-+    case OPT_MYSQL_PROTOCOL:
-+      opt_protocol =
-+          find_type_or_exit(argument, &sql_protocol_typelib, opt->name);
-+      break;
-+    case 'A':
-+      opt_rehash = false;
-+      break;
-+    case 'N':
-+      column_names = false;
-+      break;
-+    case 'e':
-+      status.batch = true;
-+      status.add_to_history = false;
-+      if (!status.line_buff)
-+        ignore_errors = false;  // do it for the first -e only
-+      if (!(status.line_buff =
-+                batch_readline_command(status.line_buff, argument)))
-+        return true;
-+      break;
-+    case 'j':
-+      if (my_openlog("MysqlClient", 0, LOG_USER)) {
-+        /* error */
-+        put_info(strerror(errno), INFO_ERROR, errno);
-+        return true;
-+      }
-+      opt_syslog = true;
-+      break;
-+    case 'o':
-+      if (argument == disabled_my_option)
-+        one_database = false;
-+      else
-+        one_database = skip_updates = true;
-+      break;
-+      PARSE_COMMAND_LINE_PASSWORD_OPTION;
-+    case '#':
-+      DBUG_PUSH(argument ? argument : default_dbug_option);
-+      debug_info_flag = true;
-+      break;
-+    case 's':
-+      if (argument == disabled_my_option)
-+        opt_silent = 0;
-+      else
-+        opt_silent++;
-+      break;
-+    case 'v':
-+      if (argument == disabled_my_option)
-+        verbose = 0;
-+      else
-+        verbose++;
-+      break;
-+    case 'B':
-+      status.batch = true;
-+      status.add_to_history = false;
-+      opt_silent = std::max(opt_silent, 1U);  // more silent
-+      break;
-+    case 'W':
-+#ifdef _WIN32
-+      opt_protocol = MYSQL_PROTOCOL_PIPE;
-+#endif
-+      break;
-+#include "sslopt-case.h"
-+
-+#include "authentication_kerberos_clientopt-case.h"
-+
-+    case 'V':
-+      usage(1);
-+      exit(0);
-+    case 'I':
-+    case '?':
-+      usage(0);
-+      exit(0);
-+    case OPT_MYSQL_BINARY_AS_HEX:
-+      opt_binhex = (argument != disabled_my_option);
-+      opt_binary_as_hex_set_explicitly = true;
-+      break;
-+    case 'C':
-+      CLIENT_WARN_DEPRECATED("--compress", "--compression-algorithms");
-+      break;
-+  }
-+  return false;
-+}
-+
-+static int get_options(int argc, char **argv) {
-+  char *tmp, *pagpoint;
-+  int ho_error;
-+
-+  tmp = (char *)getenv("MYSQL_HOST");
-+  if (tmp) current_host = my_strdup(PSI_NOT_INSTRUMENTED, tmp, MYF(MY_WME));
-+
-+  pagpoint = getenv("PAGER");
-+  if (!((char *)(pagpoint))) {
-+    my_stpcpy(pager, "stdout");
-+    opt_nopager = true;
-+  } else
-+    my_stpcpy(pager, pagpoint);
-+  my_stpcpy(default_pager, pager);
-+
-+  if (mysql_get_option(nullptr, MYSQL_OPT_MAX_ALLOWED_PACKET,
-+                       &opt_max_allowed_packet) ||
-+      mysql_get_option(nullptr, MYSQL_OPT_NET_BUFFER_LENGTH,
-+                       &opt_max_allowed_packet)) {
-+    exit(1);
-+  }
-+
-+  if ((ho_error =
-+           handle_options(&argc, &argv, my_long_options, get_one_option)))
-+    exit(ho_error);
-+
-+  if (mysql_options(nullptr, MYSQL_OPT_MAX_ALLOWED_PACKET,
-+                    &opt_max_allowed_packet) ||
-+      mysql_options(nullptr, MYSQL_OPT_NET_BUFFER_LENGTH,
-+                    &opt_net_buffer_length)) {
-+    exit(1);
-+  }
-+
-+  if (status.batch) /* disable pager and outfile in this case */
-+  {
-+    my_stpcpy(default_pager, "stdout");
-+    my_stpcpy(pager, "stdout");
-+    opt_nopager = true;
-+    default_pager_set = false;
-+    opt_outfile = false;
-+    opt_reconnect = false;
-+    connect_flag = 0; /* Not in interactive mode */
-+  }
-+
-+  if (argc > 1) {
-+    usage(0);
-+    exit(1);
-+  }
-+  if (argc == 1) {
-+    skip_updates = false;
-+    my_free(current_db);
-+    current_db = my_strdup(PSI_NOT_INSTRUMENTED, *argv, MYF(MY_WME));
-+  }
-+  if (debug_info_flag) my_end_arg = MY_CHECK_ERROR | MY_GIVE_INFO;
-+  if (debug_check_flag) my_end_arg = MY_CHECK_ERROR;
-+
-+  if (ignore_spaces) connect_flag |= CLIENT_IGNORE_SPACE;
-+
-+  return (0);
-+}
-+
-+static int read_and_execute(bool interactive) {
-+#if defined(_WIN32)
-+  String tmpbuf;
-+  String buffer;
-+#endif
-+
-+  /*
-+    line can be allocated by:
-+    - batch_readline. Use my_free()
-+    - my_win_console_readline. Do not free, see tmpbuf.
-+    - readline. Use free()
-+  */
-+  char *line = nullptr;
-+  char in_string = 0;
-+  ulong line_number = 0;
-+  bool ml_comment = false;
-+  COMMANDS *com;
-+  size_t line_length = 0;
-+  status.exit_status = 1;
-+
-+  real_binary_mode = !interactive && opt_binary_mode;
-+  for (;;) {
-+    /* Reset as SIGINT has already got handled. */
-+    sigint_received = false;
-+
-+    if (!interactive) {
-+      /*
-+        batch_readline can return 0 on EOF or error.
-+        In that case, we need to double check that we have a valid
-+        line before actually setting line_length to read_length.
-+        */
-+      line = batch_readline(status.line_buff, real_binary_mode);
-+      if (line) {
-+        line_length = status.line_buff->read_length;
-+
-+        /*
-+          ASCII 0x00 is not allowed appearing in queries if it is not in
-+          binary mode.
-+        */
-+        if (!real_binary_mode && strlen(line) != line_length) {
-+          status.exit_status = 1;
-+          String msg;
-+          msg.append(
-+              "ASCII '\\0' appeared in the statement, but this is not "
-+              "allowed unless option --binary-mode is enabled and mysql is "
-+              "run in non-interactive mode. Set --binary-mode to 1 if ASCII "
-+              "'\\0' is expected. Query: '");
-+          msg.append(glob_buffer);
-+          msg.append(line);
-+          msg.append("'.");
-+          put_info(msg.c_ptr(), INFO_ERROR);
-+          break;
-+        }
-+
-+        /*
-+          Skip UTF8 Byte Order Marker (BOM) 0xEFBBBF.
-+          Editors like "notepad" put this marker in
-+          the very beginning of a text file when
-+          you save the file using "Unicode UTF-8" format.
-+        */
-+        if (!line_number && (uchar)line[0] == 0xEF && (uchar)line[1] == 0xBB &&
-+            (uchar)line[2] == 0xBF) {
-+          line += 3;
-+          // decrease the line length accordingly to the 3 bytes chopped
-+          line_length -= 3;
-+        }
-+      }
-+      line_number++;
-+      if (!glob_buffer.length()) status.query_start_line = line_number;
-+    } else {
-+      const char *prompt =
-+          (ml_comment               ? "   /*> "
-+           : glob_buffer.is_empty() ? construct_prompt()
-+           : !in_string             ? "    -> "
-+           : in_string == '\''      ? "    '> "
-+                               : (in_string == '`' ? "    `> " : "    \"> "));
-+      if (opt_outfile && glob_buffer.is_empty()) fflush(OUTFILE);
-+
-+#if defined(_WIN32)
-+      size_t nread;
-+      tee_fputs(prompt, stdout);
-+      if (!tmpbuf.is_alloced()) tmpbuf.alloc(65535);
-+      tmpbuf.length(0);
-+      buffer.length(0);
-+      line = my_win_console_readline(charset_info, (char *)tmpbuf.ptr(),
-+                                     tmpbuf.alloced_length(), &nread);
-+      if (line && (nread == 0)) {
-+        tee_puts("^C", stdout);
-+        reset_prompt(&in_string, &ml_comment);
-+        continue;
-+      } else if (*line == 0x1A) /* (Ctrl + Z) */
-+        break;
-+#else
-+      if (opt_outfile) fputs(prompt, OUTFILE);
-+      /*
-+        free the previous entered line.
-+      */
-+      if (line) free(line);
-+      line = readline(prompt);
-+
-+      if (sigint_received) {
-+        sigint_received = false;
-+        tee_puts("^C", stdout);
-+        reset_prompt(&in_string, &ml_comment);
-+        continue;
-+      }
-+#endif /* defined(_WIN32) */
-+      /*
-+        When Ctrl+d or Ctrl+z is pressed, the line may be NULL on some OS
-+        which may cause coredump.
-+      */
-+      if (opt_outfile && line) fprintf(OUTFILE, "%s\n", line);
-+
-+      line_length = line ? strlen(line) : 0;
-+    }
-+    // End of file or system error
-+    if (!line) {
-+      if (status.line_buff && status.line_buff->error)
-+        status.exit_status = 1;
-+      else
-+        status.exit_status = 0;
-+      break;
-+    }
-+
-+    /*
-+      Check if line is a mysql command line
-+      (We want to allow help, print and clear anywhere at line start
-+    */
-+    if ((named_cmds || glob_buffer.is_empty()) && !ml_comment && !in_string &&
-+        (com = find_command(line))) {
-+      if ((*com->func)(&glob_buffer, line) > 0) {
-+        // lets log the exit/quit command.
-+        if (interactive && status.add_to_history && com->cmd_char == 'q')
-+          add_filtered_history(line);
-+        break;
-+      }
-+      if (glob_buffer.is_empty())  // If buffer was emptied
-+        in_string = 0;
-+      if (interactive && status.add_to_history) add_filtered_history(line);
-+      continue;
-+    }
-+    if (add_line(glob_buffer, line, line_length, &in_string, &ml_comment,
-+                 status.line_buff ? status.line_buff->truncated : false))
-+      break;
-+  }
-+  /* if in batch mode, send last query even if it doesn't end with \g or go */
-+
-+  if (!interactive && !status.exit_status) {
-+    remove_cntrl(&glob_buffer);
-+    if (!glob_buffer.is_empty()) {
-+      status.exit_status = 1;
-+      if (com_go(&glob_buffer, line) <= 0) status.exit_status = 0;
-+    }
-+  }
-+
-+#if defined(_WIN32)
-+  buffer.mem_free();
-+  tmpbuf.mem_free();
-+#else
-+  if (interactive)
-+    /*
-+      free the last entered line.
-+    */
-+    free(line);
-+#endif
-+
-+  /*
-+    If the function is called by 'source' command, it will return to
-+    interactive mode, so real_binary_mode should be false. Otherwise, it will
-+    exit the program, it is safe to set real_binary_mode to false.
-+  */
-+  real_binary_mode = false;
-+  return status.exit_status;
-+}
-+
-+static inline void reset_prompt(char *in_string, bool *ml_comment) {
-+  glob_buffer.length(0);
-+  *ml_comment = false;
-+  *in_string = 0;
-+}
-+
-+/**
-+   It checks if the input is a short form command. It returns the command's
-+   pointer if a command is found, else return NULL. Note that if binary-mode
-+   is set, then only @\C is searched for.
-+
-+   @param cmd_char    A character of one byte.
-+
-+   @return
-+     the command's pointer or NULL.
-+*/
-+static COMMANDS *find_command(char cmd_char) {
-+  DBUG_TRACE;
-+  DBUG_PRINT("enter", ("cmd_char: %d", cmd_char));
-+
-+  int index = -1;
-+
-+  /*
-+    In binary-mode, we disallow all mysql commands except '\C'
-+    and DELIMITER.
-+  */
-+  if (real_binary_mode) {
-+    if (cmd_char == 'C') index = charset_index;
-+  } else
-+    index = get_command_index(cmd_char);
-+
-+  if (index >= 0) {
-+    DBUG_PRINT("exit", ("found command: %s", commands[index].name));
-+    return &commands[index];
-+  } else
-+    return (COMMANDS *)nullptr;
-+}
-+
-+/**
-+   It checks if the input is a long form command. It returns the command's
-+   pointer if a command is found, else return NULL. Note that if binary-mode
-+   is set, then only DELIMITER is searched for.
-+
-+   @param name    A string.
-+   @return
-+     the command's pointer or NULL.
-+*/
-+static COMMANDS *find_command(char *name) {
-+  uint len;
-+  char *end;
-+  DBUG_TRACE;
-+
-+  assert(name != nullptr);
-+  DBUG_PRINT("enter", ("name: '%s'", name));
-+
-+  while (my_isspace(charset_info, *name)) name++;
-+  /*
-+    If there is an \\g in the row or if the row has a delimiter but
-+    this is not a delimiter command, let add_line() take care of
-+    parsing the row and calling find_command().
-+  */
-+  if ((!real_binary_mode && strstr(name, "\\g")) ||
-+      (strstr(name, delimiter) &&
-+       !is_delimiter_command(name, DELIMITER_NAME_LEN)))
-+    return (COMMANDS *)nullptr;
-+
-+  if ((end = strcont(name, " \t"))) {
-+    len = (uint)(end - name);
-+    while (my_isspace(charset_info, *end)) end++;
-+    if (!*end) end = nullptr;  // no arguments to function
-+  } else
-+    len = (uint)strlen(name);
-+
-+  int index = -1;
-+  if (real_binary_mode) {
-+    if (is_delimiter_command(name, len)) index = delimiter_index;
-+  } else {
-+    /*
-+      All commands are in the first part of commands array and have a function
-+      to implement it.
-+    */
-+    for (uint i = 0; commands[i].func; i++) {
-+      if (!my_strnncoll(&my_charset_latin1, (uchar *)name, len,
-+                        pointer_cast<const uchar *>(commands[i].name), len) &&
-+          (commands[i].name[len] == '\0') &&
-+          (!end || commands[i].takes_params)) {
-+        index = i;
-+        break;
-+      }
-+    }
-+  }
-+
-+  if (index >= 0) {
-+    DBUG_PRINT("exit", ("found command: %s", commands[index].name));
-+    return &commands[index];
-+  }
-+  return (COMMANDS *)nullptr;
-+}
-+
-+static bool add_line(String &buffer, char *line, size_t line_length,
-+                     char *in_string, bool *ml_comment, bool truncated) {
-+  uchar inchar;
-+  char buff[80], *pos, *out;
-+  COMMANDS *com;
-+  bool need_space = false;
-+  enum { SSC_NONE = 0, SSC_CONDITIONAL, SSC_HINT } ss_comment = SSC_NONE;
-+  DBUG_TRACE;
-+
-+  if (!line[0] && buffer.is_empty()) return false;
-+
-+  if (status.add_to_history && line[0]) add_filtered_history(line);
-+
-+  char *end_of_line = line + line_length;
-+
-+  for (pos = out = line; pos < end_of_line; pos++) {
-+    inchar = (uchar)*pos;
-+    if (!preserve_comments) {
-+      // Skip spaces at the beginning of a statement
-+      if (my_isspace(charset_info, inchar) && (out == line) &&
-+          buffer.is_empty())
-+        continue;
-+    }
-+    // Accept multi-byte characters as-is
-+    int length;
-+    if (use_mb(charset_info) &&
-+        (length = my_ismbchar(charset_info, pos, end_of_line))) {
-+      if (!*ml_comment || preserve_comments) {
-+        while (length--) *out++ = *pos++;
-+        pos--;
-+      } else
-+        pos += length - 1;
-+      continue;
-+    }
-+    if (!*ml_comment && inchar == '\\' &&
-+        !(*in_string &&
-+          (mysql.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES))) {
-+      // Found possbile one character command like \c
-+
-+      if (!(inchar = (uchar) * ++pos)) break;  // readline adds one '\'
-+      if (*in_string || inchar == 'N')         // \N is short for NULL
-+      {                                        // Don't allow commands in string
-+        *out++ = '\\';
-+        if ((inchar == '`') && (*in_string == inchar))
-+          pos--;
-+        else
-+          *out++ = (char)inchar;
-+        continue;
-+      }
-+      if ((com = find_command((char)inchar))) {
-+        // Flush previously accepted characters
-+        if (out != line) {
-+          buffer.append(line, (uint)(out - line));
-+          out = line;
-+        }
-+
-+        if ((*com->func)(&buffer, pos - 1) > 0) return true;  // Quit
-+        if (com->takes_params) {
-+          if (ss_comment) {
-+            /*
-+              If a client-side macro appears inside a server-side comment,
-+              discard all characters in the comment after the macro (that is,
-+              until the end of the comment rather than the next delimiter)
-+            */
-+            for (pos++; *pos && (*pos != '*' || *(pos + 1) != '/'); pos++)
-+              ;
-+            pos--;
-+          } else {
-+            for (pos++; *pos && (*pos != *delimiter ||
-+                                 !is_prefix(pos + 1, delimiter + 1));
-+                 pos++)
-+              ;  // Remove parameters
-+            if (!*pos)
-+              pos--;
-+            else
-+              pos += delimiter_length - 1;  // Point at last delim char
-+          }
-+        }
-+      } else {
-+        sprintf(buff, "Unknown command '\\%c'.", inchar);
-+        if (put_info(buff, INFO_ERROR) > 0) return true;
-+        *out++ = '\\';
-+        *out++ = (char)inchar;
-+        continue;
-+      }
-+    } else if (!*ml_comment && !*in_string && ss_comment != SSC_HINT &&
-+               is_prefix(pos, delimiter)) {
-+      // Found a statement. Continue parsing after the delimiter
-+      pos += delimiter_length;
-+
-+      if (preserve_comments) {
-+        while (my_isspace(charset_info, *pos)) *out++ = *pos++;
-+      }
-+      // Flush previously accepted characters
-+      if (out != line) {
-+        buffer.append(line, (uint32)(out - line));
-+        out = line;
-+      }
-+
-+      if (preserve_comments &&
-+          ((*pos == '#') || ((*pos == '-') && (pos[1] == '-') &&
-+                             my_isspace(charset_info, pos[2])))) {
-+        // Add trailing single line comments to this statement
-+        buffer.append(pos);
-+        pos += strlen(pos);
-+      }
-+
-+      pos--;
-+
-+      if ((com = find_command(buffer.c_ptr()))) {
-+        if ((*com->func)(&buffer, buffer.c_ptr()) > 0) return true;  // Quit
-+      } else {
-+        if (com_go(&buffer, nullptr) > 0)  // < 0 is not fatal
-+          return true;
-+      }
-+      buffer.length(0);
-+    } else if (!*ml_comment &&
-+               (!*in_string &&
-+                (inchar == '#' ||
-+                 (inchar == '-' && pos[1] == '-' &&
-+                  /*
-+                    The third byte is either whitespace or is the
-+                    end of the line -- which would occur only
-+                    because of the user sending newline -- which is
-+                    itself whitespace and should also match.
-+                  */
-+                  (my_isspace(charset_info, pos[2]) || !pos[2]))))) {
-+      // Flush previously accepted characters
-+      if (out != line) {
-+        buffer.append(line, (uint32)(out - line));
-+        out = line;
-+      }
-+
-+      // comment to end of line
-+      if (preserve_comments) {
-+        bool started_with_nothing = !buffer.length();
-+
-+        buffer.append(pos);
-+
-+        /*
-+          A single-line comment by itself gets sent immediately so that
-+          client commands (delimiter, status, etc) will be interpreted on
-+          the next line.
-+        */
-+        if (started_with_nothing) {
-+          if (com_go(&buffer, nullptr) > 0)  // < 0 is not fatal
-+            return true;
-+          buffer.length(0);
-+        }
-+      }
-+
-+      break;
-+    } else if (!*in_string && inchar == '/' && pos[1] == '*' && pos[2] != '!' &&
-+               pos[2] != '+' && ss_comment != SSC_HINT) {
-+      if (preserve_comments) {
-+        *out++ = *pos++;  // copy '/'
-+        *out++ = *pos;    // copy '*'
-+      } else
-+        pos++;
-+      *ml_comment = true;
-+      if (out != line) {
-+        buffer.append(line, (uint)(out - line));
-+        out = line;
-+      }
-+    } else if (*ml_comment && !ss_comment && inchar == '*' &&
-+               *(pos + 1) == '/') {
-+      if (preserve_comments) {
-+        *out++ = *pos++;  // copy '*'
-+        *out++ = *pos;    // copy '/'
-+      } else
-+        pos++;
-+      *ml_comment = false;
-+      if (out != line) {
-+        buffer.append(line, (uint32)(out - line));
-+        out = line;
-+      }
-+      // Consumed a 2 chars or more, and will add 1 at most,
-+      // so using the 'line' buffer to edit data in place is ok.
-+      need_space = true;
-+    } else {  // Add found char to buffer
-+      if (!*in_string && inchar == '/' && pos[1] == '*') {
-+        if (pos[2] == '!')
-+          ss_comment = SSC_CONDITIONAL;
-+        else if (pos[2] == '+')
-+          ss_comment = SSC_HINT;
-+      } else if (!*in_string && ss_comment && inchar == '*' &&
-+                 *(pos + 1) == '/')
-+        ss_comment = SSC_NONE;
-+      if (inchar == *in_string)
-+        *in_string = 0;
-+      else if (!*ml_comment && !*in_string && ss_comment != SSC_HINT &&
-+               (inchar == '\'' || inchar == '"' || inchar == '`'))
-+        *in_string = (char)inchar;
-+      if (!*ml_comment || preserve_comments) {
-+        if (need_space && !my_isspace(charset_info, (char)inchar)) *out++ = ' ';
-+        need_space = false;
-+        *out++ = (char)inchar;
-+      }
-+    }
-+  }
-+  if (out != line || !buffer.is_empty()) {
-+    uint length = (uint)(out - line);
-+
-+    if (!truncated &&
-+        (!is_delimiter_command(line, length) || (*in_string || *ml_comment))) {
-+      /*
-+        Don't add a new line in case there's a DELIMITER command to be
-+        added to the glob buffer (e.g. on processing a line like
-+        "<command>;DELIMITER <non-eof>") : similar to how a new line is
-+        not added in the case when the DELIMITER is the first command
-+        entered with an empty glob buffer. However, if the delimiter is
-+        part of a string or a comment, the new line should be added. (e.g.
-+        SELECT '\ndelimiter\n';\n)
-+      */
-+      *out++ = '\n';
-+      length++;
-+    }
-+    if (buffer.length() + length >= buffer.alloced_length())
-+      buffer.mem_realloc(buffer.length() + length + batch_io_size);
-+    if ((!*ml_comment || preserve_comments) && buffer.append(line, length))
-+      return true;
-+  }
-+  return false;
-+}
-+
-+/*****************************************************************
-+            Interface to Readline Completion
-+******************************************************************/
-+
-+#ifdef HAVE_READLINE
-+
-+static char *new_command_generator(const char *text, int);
-+static char **new_mysql_completion(const char *text, int start, int end);
-+
-+/*
-+  Tell the GNU Readline library how to complete.  We want to try to complete
-+  on command names if this is the first word in the line, or on filenames
-+  if not.
-+*/
-+
-+#if defined(EDITLINE_HAVE_COMPLETION_CHAR)
-+char *no_completion(const char *, int) { return nullptr; }
-+#elif defined(EDITLINE_HAVE_COMPLETION_INT)
-+int no_completion(const char *, int) { return 0; }
-+#else
-+char *no_completion() { return nullptr; }
-+#endif
-+
-+/*
-+  returns 0 if line matches the previous history entry
-+  returns 1 if the line doesn't match the previous history entry
-+*/
-+static int not_in_history(const char *line) {
-+  HIST_ENTRY *oldhist = history_get(history_length);
-+
-+  if (oldhist == nullptr) return 1;
-+  if (strcmp(oldhist->line, line) == 0) return 0;
-+  return 1;
-+}
-+
-+#if defined(USE_NEW_EDITLINE_INTERFACE)
-+static int fake_magic_space(int, int)
-+#else
-+static int fake_magic_space(const char *, int)
-+#endif
-+{
-+  rl_insert(1, ' ');
-+  return 0;
-+}
-+
-+static void initialize_readline(char *name) {
-+  /* Allow conditional parsing of the ~/.inputrc file. */
-+  rl_readline_name = name;
-+
-+  /* Accept all locales. */
-+  setlocale(LC_ALL, "");
-+
-+  /* Tell the completer that we want a crack first. */
-+#if defined(EDITLINE_HAVE_COMPLETION_CHAR)
-+  rl_attempted_completion_function = &new_mysql_completion;
-+  rl_completion_entry_function = &no_completion;
-+
-+  rl_add_defun("magic-space", &fake_magic_space, -1);
-+#elif defined(EDITLINE_HAVE_COMPLETION_INT)
-+  rl_attempted_completion_function = &new_mysql_completion;
-+  rl_completion_entry_function = &no_completion;
-+  rl_add_defun("magic-space", &fake_magic_space, -1);
-+#else
-+  rl_attempted_completion_function = (CPPFunction *)&new_mysql_completion;
-+  rl_completion_entry_function = &no_completion;
-+#endif
-+}
-+
-+/*
-+  Attempt to complete on the contents of TEXT.  START and END show the
-+  region of TEXT that contains the word to complete.  We can use the
-+  entire line in case we want to do some simple parsing.  Return the
-+  array of matches, or NULL if there aren't any.
-+*/
-+
-+static char **new_mysql_completion(const char *text, int start [[maybe_unused]],
-+                                   int end [[maybe_unused]]) {
-+  if (!status.batch && !quick)
-+#if defined(USE_NEW_EDITLINE_INTERFACE)
-+    return rl_completion_matches(text, new_command_generator);
-+#else
-+    return completion_matches(const_cast<char *>(text), new_command_generator);
-+#endif
-+  else
-+    return (char **)nullptr;
-+}
-+
-+static char *new_command_generator(const char *text, int state) {
-+  static int textlen;
-+  char *ptr;
-+  static Bucket *b;
-+  static entry *e;
-+  static uint i;
-+
-+  if (!state) textlen = (uint)strlen(text);
-+
-+  if (textlen > 0) { /* lookup in the hash */
-+    if (!state) {
-+      uint len;
-+
-+      b = find_all_matches(&ht, text, (uint)strlen(text), &len);
-+      if (!b) return NullS;
-+      e = b->pData;
-+    }
-+
-+    if (e) {
-+      ptr = strdup(e->str);
-+      e = e->pNext;
-+      return ptr;
-+    }
-+  } else { /* traverse the entire hash, ugly but works */
-+
-+    if (!state) {
-+      /* find the first used bucket */
-+      for (i = 0; i < ht.nTableSize; i++) {
-+        if (ht.arBuckets[i]) {
-+          b = ht.arBuckets[i];
-+          e = b->pData;
-+          break;
-+        }
-+      }
-+    }
-+    ptr = NullS;
-+    while (e && !ptr) { /* find valid entry in bucket */
-+      if ((uint)strlen(e->str) == b->nKeyLength) ptr = strdup(e->str);
-+      /* find the next used entry */
-+      e = e->pNext;
-+      if (!e) { /* find the next used bucket */
-+        b = b->pNext;
-+        if (!b) {
-+          for (i++; i < ht.nTableSize; i++) {
-+            if (ht.arBuckets[i]) {
-+              b = ht.arBuckets[i];
-+              e = b->pData;
-+              break;
-+            }
-+          }
-+        } else
-+          e = b->pData;
-+      }
-+    }
-+    if (ptr) return ptr;
-+  }
-+  return NullS;
-+}
-+
-+/* Build up the completion hash */
-+
-+static void build_completion_hash(bool rehash, bool write_info) {
-+  COMMANDS *cmd = commands;
-+  MYSQL_RES *databases = nullptr, *tables = nullptr;
-+  MYSQL_RES *fields;
-+  static char ***field_names = nullptr;
-+  MYSQL_ROW database_row, table_row;
-+  MYSQL_FIELD *sql_field;
-+  char buf[NAME_LEN * 2 + 2];  // table name plus field name plus 2
-+  int i, j, num_fields;
-+  DBUG_TRACE;
-+
-+#ifndef NDEBUG
-+  if (!opt_build_completion_hash)
-+#endif
-+  {
-+    if (status.batch || quick || !current_db)
-+      return;  // We don't need completion in batches
-+  }
-+
-+  if (!rehash) return;
-+
-+  /* Free old used memory */
-+  if (field_names) field_names = nullptr;
-+  completion_hash_clean(&ht);
-+  hash_mem_root.Clear();
-+
-+  /* hash this file's known subset of SQL commands */
-+  while (cmd->name) {
-+    add_word(&ht, cmd->name);
-+    cmd++;
-+  }
-+
-+  /* hash MySQL functions (to be implemented) */
-+
-+  /* hash all database names */
-+  if (mysql_query(&mysql, "show databases") == 0) {
-+    if (!(databases = mysql_store_result(&mysql)))
-+      put_info(mysql_error(&mysql), INFO_INFO);
-+    else {
-+      while ((database_row = mysql_fetch_row(databases))) {
-+        char *str = strdup_root(&hash_mem_root, (char *)database_row[0]);
-+        if (str) add_word(&ht, (char *)str);
-+      }
-+      mysql_free_result(databases);
-+    }
-+  }
-+  /* hash all table names */
-+  if (mysql_query(&mysql, "show tables") == 0) {
-+    if (!(tables = mysql_store_result(&mysql)))
-+      put_info(mysql_error(&mysql), INFO_INFO);
-+    else {
-+      if (mysql_num_rows(tables) > 0 && !opt_silent && write_info) {
-+        tee_fprintf(stdout,
-+                    "\
-+Reading table information for completion of table and column names\n\
-+You can turn off this feature to get a quicker startup with -A\n\n");
-+      }
-+      while ((table_row = mysql_fetch_row(tables))) {
-+        char *str = strdup_root(&hash_mem_root, (char *)table_row[0]);
-+        if (str && !completion_hash_exists(&ht, (char *)str, (uint)strlen(str)))
-+          add_word(&ht, str);
-+      }
-+    }
-+  }
-+
-+  /* hash all field names, both with the table prefix and without it */
-+  if (!tables) /* no tables */
-+  {
-+    return;
-+  }
-+  mysql_data_seek(tables, 0);
-+  if (!(field_names = (char ***)hash_mem_root.Alloc(
-+            sizeof(char **) * (uint)(mysql_num_rows(tables) + 1)))) {
-+    mysql_free_result(tables);
-+    return;
-+  }
-+  i = 0;
-+  while ((table_row = mysql_fetch_row(tables))) {
-+    if ((fields =
-+             mysql_list_fields(&mysql, (const char *)table_row[0], NullS))) {
-+      num_fields = mysql_num_fields(fields);
-+      if (!(field_names[i] = (char **)hash_mem_root.Alloc(
-+                sizeof(char *) * (num_fields * 2 + 1)))) {
-+        mysql_free_result(fields);
-+        break;
-+      }
-+      field_names[i][num_fields * 2] = nullptr;
-+      j = 0;
-+      while ((sql_field = mysql_fetch_field(fields))) {
-+        sprintf(buf, "%.64s.%.64s", table_row[0], sql_field->name);
-+        field_names[i][j] = strdup_root(&hash_mem_root, buf);
-+        add_word(&ht, field_names[i][j]);
-+        field_names[i][num_fields + j] =
-+            strdup_root(&hash_mem_root, sql_field->name);
-+        if (!completion_hash_exists(
-+                &ht, field_names[i][num_fields + j],
-+                (uint)strlen(field_names[i][num_fields + j])))
-+          add_word(&ht, field_names[i][num_fields + j]);
-+        j++;
-+      }
-+      mysql_free_result(fields);
-+    } else
-+      field_names[i] = nullptr;
-+
-+    i++;
-+  }
-+  mysql_free_result(tables);
-+  field_names[i] = nullptr;  // End pointer
-+}
-+
-+/* for gnu readline */
-+
-+#ifndef HAVE_INDEX
-+extern "C" {
-+extern char *index(const char *, int c), *rindex(const char *, int);
-+
-+char *index(const char *s, int c) {
-+  for (;;) {
-+    if (*s == (char)c) return (char *)s;
-+    if (!*s++) return NullS;
-+  }
-+}
-+
-+char *rindex(const char *s, int c) {
-+  char *t;
-+
-+  t = NullS;
-+  do
-+    if (*s == (char)c) t = (char *)s;
-+  while (*s++);
-+  return (char *)t;
-+}
-+}
-+#endif /* ! HAVE_INDEX */
-+#endif /* HAVE_READLINE */
-+
-+static void fix_line(String *final_command) {
-+  int total_lines = 1;
-+  char *ptr = final_command->c_ptr();
-+  String fixed_buffer; /* Converted buffer */
-+
-+  /* Character if we are in a string or not */
-+  char str_char = '\0';
-+
-+  /* find out how many lines we have and remove newlines */
-+  while (*ptr != '\0') {
-+    switch (*ptr) {
-+      /* string character */
-+      case '"':
-+      case '\'':
-+      case '`':
-+        if (str_char == '\0') /* open string */
-+          str_char = *ptr;
-+        else if (str_char == *ptr) /* close string */
-+          str_char = '\0';
-+        fixed_buffer.append(ptr, 1);
-+        break;
-+      case '\n':
-+        /* not in string, change to space if in string, leave it alone */
-+        fixed_buffer.append(str_char == '\0' ? " " : "\n");
-+        total_lines++;
-+        break;
-+      case '\\':
-+        fixed_buffer.append('\\');
-+        /* need to see if the backslash is escaping anything */
-+        if (str_char) {
-+          ptr++;
-+          /* special characters that need escaping */
-+          if (*ptr == '\'' || *ptr == '"' || *ptr == '\\')
-+            fixed_buffer.append(ptr, 1);
-+          else
-+            ptr--;
-+        }
-+        break;
-+
-+      default:
-+        fixed_buffer.append(ptr, 1);
-+    }
-+    ptr++;
-+  }
-+  if (total_lines > 1) add_filtered_history(fixed_buffer.ptr());
-+}
-+
-+/* Add the given line to mysql history and syslog. */
-+static void add_filtered_history(const char *string) {
-+  // line shouldn't be on history ignore list
-+  if (ignore_matcher.is_matching(string, charset_info)) return;
-+
-+#ifdef HAVE_READLINE
-+  if (!quick && not_in_history(string)) add_history(string);
-+#endif
-+
-+  if (opt_syslog) add_syslog(string);
-+}
-+
-+void add_syslog(const char *line) {
-+  char buff[MAX_SYSLOG_MESSAGE_SIZE];
-+  snprintf(buff, sizeof(buff),
-+           "SYSTEM_USER:'%s', MYSQL_USER:'%s', "
-+           "CONNECTION_ID:%lu, DB_SERVER:'%s', DB:'%s', QUERY:'%s'",
-+           /* use the cached user/sudo_user value. */
-+           current_os_sudouser ? current_os_sudouser
-+           : current_os_user   ? current_os_user
-+                               : "--",
-+           current_user ? current_user : "--", mysql_thread_id(&mysql),
-+           current_host ? current_host : "--", current_db ? current_db : "--",
-+           line);
-+
-+  (void)my_syslog(charset_info, INFORMATION_LEVEL, buff);
-+  return;
-+}
-+
-+static int reconnect(void) {
-+  /* purecov: begin tested */
-+  if (opt_reconnect) {
-+    put_info("No connection. Trying to reconnect...", INFO_INFO);
-+    (void)com_connect((String *)nullptr, nullptr);
-+    if (opt_rehash && connected) com_rehash(nullptr, nullptr);
-+  }
-+  if (!connected) return put_info("Can't connect to the server\n", INFO_ERROR);
-+  /* purecov: end */
-+  return 0;
-+}
-+
-+/**
-+  Checks the current DB and updates the global variable current_db
-+  If the command fails hen he current_db is set to nullptr.
-+
-+  @return Error state
-+    @retval true An error occurred
-+    @retval false Success; current_db is updated
-+*/
-+static bool get_current_db() {
-+  MYSQL_RES *res;
-+
-+  /* If one_database is set, current_db is not supposed to change. */
-+  if (one_database) return false;
-+
-+  my_free(current_db);
-+  current_db = nullptr;
-+  /* In case of error below current_db will be NULL */
-+  if (!mysql_query(&mysql, "SELECT DATABASE()") &&
-+      (res = mysql_use_result(&mysql))) {
-+    MYSQL_ROW row = mysql_fetch_row(res);
-+    if (row && row[0])
-+      current_db = my_strdup(PSI_NOT_INSTRUMENTED, row[0], MYF(MY_WME));
-+    mysql_free_result(res);
-+  } else {
-+    /* We failed to issue the command and we likely lost connection */
-+    return true;
-+  }
-+  return false;
-+}
-+
-+/***************************************************************************
-+ The different commands
-+***************************************************************************/
-+
-+static int mysql_real_query_for_lazy(const char *buf, size_t length,
-+                                     bool set_params = false) {
-+  int error = 0;
-+  for (uint retry = 0;; retry++) {
-+    error = 0;
-+
-+    if (set_params && global_attrs->set_params(&mysql)) break;
-+    if (!mysql_real_query(&mysql, buf, (ulong)length)) break;
-+    error = put_error(&mysql);
-+    if ((mysql_errno(&mysql) != CR_SERVER_GONE_ERROR &&
-+         mysql_errno(&mysql) != CR_SERVER_LOST &&
-+         mysql.net.error != NET_ERROR_SOCKET_UNUSABLE) ||
-+        retry > 1 || !opt_reconnect)
-+      break;
-+    if (reconnect()) break;
-+  }
-+  if (set_params) global_attrs->clear(connected ? &mysql : nullptr);
-+  return error;
-+}
-+
-+static int mysql_store_result_for_lazy(MYSQL_RES **result) {
-+  if ((*result = mysql_store_result(&mysql))) return 0;
-+
-+  if (mysql_error(&mysql)[0]) return put_error(&mysql);
-+  return 0;
-+}
-+
-+static void print_help_item(MYSQL_ROW *cur, int num_name, int num_cat,
-+                            char *last_char) {
-+  char ccat = (*cur)[num_cat][0];
-+  if (*last_char != ccat) {
-+    put_info(ccat == 'Y' ? "categories:" : "topics:", INFO_INFO);
-+    *last_char = ccat;
-+  }
-+  tee_fprintf(PAGER, "   %s\n", (*cur)[num_name]);
-+}
-+
-+static int com_server_help(String *buffer [[maybe_unused]],
-+                           char *line [[maybe_unused]], char *help_arg) {
-+  MYSQL_ROW cur;
-+  const char *server_cmd;
-+  char cmd_buf[100 + 1];
-+  MYSQL_RES *result;
-+  int error;
-+
-+  if (help_arg[0] != '\'') {
-+    char *end_arg = strend(help_arg);
-+    if (--end_arg) {
-+      while (my_isspace(charset_info, *end_arg)) end_arg--;
-+      *++end_arg = '\0';
-+    }
-+    (void)strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS);
-+  } else
-+    (void)strxnmov(cmd_buf, sizeof(cmd_buf), "help ", help_arg, NullS);
-+
-+  server_cmd = cmd_buf;
-+
-+  if (!status.batch) {
-+    old_buffer = *buffer;
-+    old_buffer.copy();
-+  }
-+
-+  if (!connected && reconnect()) return 1;
-+
-+  if ((error =
-+           mysql_real_query_for_lazy(server_cmd, (int)strlen(server_cmd))) ||
-+      (error = mysql_store_result_for_lazy(&result)))
-+    return error;
-+
-+  if (result) {
-+    unsigned int num_fields = mysql_num_fields(result);
-+    uint64_t num_rows = mysql_num_rows(result);
-+    mysql_fetch_fields(result);
-+    if (num_fields == 3 && num_rows == 1) {
-+      if (!(cur = mysql_fetch_row(result))) {
-+        error = -1;
-+        goto err;
-+      }
-+
-+      init_pager();
-+      tee_fprintf(PAGER, "Name: \'%s\'\n", cur[0]);
-+      tee_fprintf(PAGER, "Description:\n%s", cur[1]);
-+      if (cur[2] && *((char *)cur[2]))
-+        tee_fprintf(PAGER, "Examples:\n%s", cur[2]);
-+      tee_fprintf(PAGER, "\n");
-+      end_pager();
-+    } else if (num_fields >= 2 && num_rows) {
-+      init_pager();
-+      char last_char = 0;
-+
-+      int num_name = 0, num_cat = 0;
-+
-+      if (num_fields == 2) {
-+        put_info("Many help items for your request exist.", INFO_INFO);
-+        put_info(
-+            "To make a more specific request, please type 'help "
-+            "<item>',\nwhere <item> is one of the following",
-+            INFO_INFO);
-+        num_name = 0;
-+        num_cat = 1;
-+      } else if ((cur = mysql_fetch_row(result))) {
-+        tee_fprintf(PAGER, "You asked for help about help category: \"%s\"\n",
-+                    cur[0]);
-+        put_info(
-+            "For more information, type 'help <item>', where <item> is one "
-+            "of "
-+            "the following",
-+            INFO_INFO);
-+        num_name = 1;
-+        num_cat = 2;
-+        print_help_item(&cur, 1, 2, &last_char);
-+      }
-+
-+      while ((cur = mysql_fetch_row(result)))
-+        print_help_item(&cur, num_name, num_cat, &last_char);
-+      tee_fprintf(PAGER, "\n");
-+      end_pager();
-+    } else {
-+      put_info("\nNothing found", INFO_INFO);
-+      if (native_strncasecmp(server_cmd, "help 'contents'", 15) == 0) {
-+        put_info("\nPlease check if 'help tables' are loaded.\n", INFO_INFO);
-+        goto err;
-+      }
-+      put_info(
-+          "Please try to run 'help contents' for a list of all accessible "
-+          "topics\n",
-+          INFO_INFO);
-+    }
-+  }
-+
-+err:
-+  mysql_free_result(result);
-+  return error;
-+}
-+
-+static int com_help(String *buffer [[maybe_unused]],
-+                    char *line [[maybe_unused]]) {
-+  int i, j;
-+  char *help_arg = strchr(line, ' '), buff[32], *end;
-+  if (help_arg) {
-+    while (my_isspace(charset_info, *help_arg)) help_arg++;
-+    if (*help_arg) return com_server_help(buffer, line, help_arg);
-+  }
-+
-+  put_info(
-+      "\nFor information about MySQL products and services, visit:\n"
-+      "   http://www.mysql.com/\n"
-+      "For developer information, including the MySQL Reference Manual, "
-+      "visit:\n"
-+      "   http://dev.mysql.com/\n"
-+      "To buy MySQL Enterprise support, training, or other products, visit:\n"
-+      "   https://shop.mysql.com/\n",
-+      INFO_INFO);
-+  put_info("List of all MySQL commands:", INFO_INFO);
-+  if (!named_cmds)
-+    put_info(
-+        "Note that all text commands must be first on line and end with ';'",
-+        INFO_INFO);
-+  for (i = 0; commands[i].name; i++) {
-+    end = my_stpcpy(buff, commands[i].name);
-+    for (j = (int)strlen(commands[i].name); j < 10; j++)
-+      end = my_stpcpy(end, " ");
-+    if (commands[i].func) {
-+      if (commands[i].cmd_char)
-+        tee_fprintf(stdout, "%s(\\%c) %s\n", buff, commands[i].cmd_char,
-+                    commands[i].doc);
-+      else
-+        tee_fprintf(stdout, "%s %s\n", buff, commands[i].doc);
-+    }
-+  }
-+  if (connected && mysql_get_server_version(&mysql) >= 40100)
-+    put_info("\nFor server side help, type 'help contents'\n", INFO_INFO);
-+  return 0;
-+}
-+
-+/* ARGSUSED */
-+static int com_clear(String *buffer, char *line [[maybe_unused]]) {
-+  if (status.add_to_history) fix_line(buffer);
-+  buffer->length(0);
-+  return 0;
-+}
-+
-+/* ARGSUSED */
-+static int com_charset(String *buffer [[maybe_unused]], char *line) {
-+  char buff[256], *param;
-+  const CHARSET_INFO *new_cs;
-+  strmake(buff, line, sizeof(buff) - 1);
-+  param = get_arg(buff, false);
-+  if (!param || !*param) {
-+    return put_info("Usage: \\C charset_name | charset charset_name",
-+                    INFO_ERROR, 0);
-+  }
-+  new_cs = get_charset_by_csname(param, MY_CS_PRIMARY, MYF(MY_WME));
-+  if (new_cs) {
-+    charset_info = new_cs;
-+    mysql_set_character_set(&mysql, charset_info->csname);
-+    default_charset = charset_info->csname;
-+    put_info("Charset changed", INFO_INFO);
-+  } else
-+    put_info("Charset is not found", INFO_INFO);
-+  return 0;
-+}
-+
-+/*
-+  Execute command
-+  Returns: 0  if ok
-+          -1 if not fatal error
-+          1  if fatal error
-+*/
-+
-+static int com_go(String *buffer, char *line [[maybe_unused]]) {
-+  char buff[200];             /* about 110 chars used so far */
-+  char time_buff[52 + 3 + 1]; /* time max + space&parens + NUL */
-+  MYSQL_RES *result;
-+  ulong timer, warnings = 0;
-+  uint error = 0;
-+  int err = 0;
-+
-+  interrupted_query = false;
-+  if (!status.batch) {
-+    old_buffer = *buffer;  // Save for edit command
-+    old_buffer.copy();
-+  }
-+
-+  /* Remove garbage for nicer messages */
-+  buff[0] = 0;
-+  remove_cntrl(buffer);
-+
-+  if (buffer->is_empty()) {
-+    if (status.batch)  // Ignore empty quries
-+      return 0;
-+    return put_info("No query specified\n", INFO_ERROR);
-+  }
-+  if (!connected && reconnect()) {
-+    buffer->length(0);              // Remove query on error
-+    return opt_reconnect ? -1 : 1;  // Fatal error
-+  }
-+  if (verbose) (void)com_print(buffer, nullptr);
-+
-+  if (skip_updates && (buffer->length() < 4 ||
-+                       my_strnncoll(charset_info, (const uchar *)buffer->ptr(),
-+                                    4, (const uchar *)"SET ", 4))) {
-+    (void)put_info("Ignoring query to other database", INFO_INFO);
-+    return 0;
-+  }
-+
-+  timer = start_timer();
-+  executing_query = true;
-+  error = mysql_real_query_for_lazy(buffer->ptr(), buffer->length(), true);
-+
-+  if (status.add_to_history) {
-+    buffer->append(vertical ? "\\G" : delimiter);
-+    /* Append final command onto history and syslog. */
-+    fix_line(buffer);
-+  }
-+  buffer->length(0);
-+
-+  if (error) goto end;
-+
-+  do {
-+    char *pos;
-+    bool batchmode = (status.batch && verbose <= 1);
-+    buff[0] = 0;
-+
-+    if (quick) {
-+      if (!(result = mysql_use_result(&mysql)) && mysql_field_count(&mysql)) {
-+        error = put_error(&mysql);
-+        goto end;
-+      }
-+    } else {
-+      error = mysql_store_result_for_lazy(&result);
-+      if (error) goto end;
-+    }
-+
-+    if (verbose >= 3 || !opt_silent)
-+      mysql_end_timer(timer, time_buff);
-+    else
-+      time_buff[0] = '\0';
-+
-+    /* Every branch must truncate  buff . */
-+    if (result) {
-+      if (!mysql_num_rows(result) && !quick && !column_types_flag) {
-+        my_stpcpy(buff, "Empty set");
-+        if (opt_xml) {
-+          /*
-+            We must print XML header and footer
-+            to produce a well-formed XML even if
-+            the result set is empty (Bug#27608).
-+          */
-+          init_pager();
-+          print_table_data_xml(result);
-+          end_pager();
-+        }
-+      } else {
-+        init_pager();
-+        if (opt_html)
-+          print_table_data_html(result);
-+        else if (opt_xml)
-+          print_table_data_xml(result);
-+        else if (vertical || (auto_vertical_output &&
-+                              (terminal_width < get_result_width(result))))
-+          print_table_data_vertically(result);
-+        else if (opt_silent && verbose <= 2 && !output_tables)
-+          print_tab_data(result);
-+        else
-+          print_table_data(result);
-+        if (!batchmode)
-+          sprintf(buff, "%" PRId64 " %s in set", mysql_num_rows(result),
-+                  mysql_num_rows(result) == 1LL ? "row" : "rows");
-+        end_pager();
-+        if (mysql_errno(&mysql)) error = put_error(&mysql);
-+      }
-+    } else if (mysql_affected_rows(&mysql) == ~(ulonglong)0)
-+      my_stpcpy(buff, "Query OK");
-+    else if (!batchmode)
-+      sprintf(buff, "Query OK, %" PRId64 " %s affected",
-+              mysql_affected_rows(&mysql),
-+              mysql_affected_rows(&mysql) == 1LL ? "row" : "rows");
-+
-+    pos = strend(buff);
-+    if ((warnings = mysql_warning_count(&mysql)) && !batchmode) {
-+      *pos++ = ',';
-+      *pos++ = ' ';
-+      pos = longlong10_to_str(warnings, pos, 10);
-+      pos = my_stpcpy(pos, " warning");
-+      if (warnings != 1) *pos++ = 's';
-+    }
-+    my_stpcpy(pos, time_buff);
-+    put_info(buff, INFO_RESULT);
-+    if (mysql_info(&mysql)) put_info(mysql_info(&mysql), INFO_RESULT);
-+    put_info("", INFO_RESULT);  // Empty row
-+
-+    if (result && !mysql_eof(result)) /* Something wrong when using quick */
-+      error = put_error(&mysql);
-+    else if (unbuffered)
-+      fflush(stdout);
-+    mysql_free_result(result);
-+  } while (!(err = mysql_next_result(&mysql)));
-+  if (err >= 1) error = put_error(&mysql);
-+
-+end:
-+
-+  /* Show warnings if any or error occurred */
-+  if (show_warnings == 1 && (warnings >= 1 || error)) print_warnings();
-+
-+  if (!error && (mysql.server_status & SERVER_STATUS_DB_DROPPED))
-+    get_current_db();
-+
-+  executing_query = false;
-+  return error; /* New command follows */
-+}
-+
-+static void init_pager() {
-+#ifdef USE_POPEN
-+  if (!opt_nopager) {
-+    if (!(PAGER = popen(pager, "w"))) {
-+      tee_fprintf(stdout, "popen() failed! defaulting PAGER to stdout!\n");
-+      PAGER = stdout;
-+    }
-+  } else
-+#endif
-+    PAGER = stdout;
-+}
-+
-+static void end_pager() {
-+#ifdef USE_POPEN
-+  if (!opt_nopager) pclose(PAGER);
-+#endif
-+}
-+
-+static void init_tee(const char *file_name) {
-+  FILE *new_outfile;
-+  if (opt_outfile) end_tee();
-+  if (!(new_outfile = my_fopen(file_name, O_APPEND | O_WRONLY, MYF(MY_WME)))) {
-+    tee_fprintf(stdout, "Error logging to file '%s'\n", file_name);
-+    return;
-+  }
-+  OUTFILE = new_outfile;
-+  strmake(outfile, file_name, FN_REFLEN - 1);
-+  tee_fprintf(stdout, "Logging to file '%s'\n", file_name);
-+  opt_outfile = true;
-+  return;
-+}
-+
-+static void end_tee() {
-+  my_fclose(OUTFILE, MYF(0));
-+  OUTFILE = nullptr;
-+  opt_outfile = false;
-+  return;
-+}
-+
-+static int com_ego(String *buffer, char *line) {
-+  int result;
-+  bool oldvertical = vertical;
-+  vertical = true;
-+  result = com_go(buffer, line);
-+  vertical = oldvertical;
-+  return result;
-+}
-+
-+const char *fieldtype2str(enum enum_field_types type);
-+
-+static char *fieldflags2str(uint f) {
-+  static char buf[1024];
-+  char *s = buf;
-+  *s = 0;
-+#define ff2s_check_flag(X)    \
-+  if (f & X##_FLAG) {         \
-+    s = my_stpcpy(s, #X " "); \
-+    f &= ~X##_FLAG;           \
-+  }
-+  ff2s_check_flag(NOT_NULL);
-+  ff2s_check_flag(PRI_KEY);
-+  ff2s_check_flag(UNIQUE_KEY);
-+  ff2s_check_flag(MULTIPLE_KEY);
-+  ff2s_check_flag(BLOB);
-+  ff2s_check_flag(UNSIGNED);
-+  ff2s_check_flag(ZEROFILL);
-+  ff2s_check_flag(BINARY);
-+  ff2s_check_flag(ENUM);
-+  ff2s_check_flag(AUTO_INCREMENT);
-+  ff2s_check_flag(TIMESTAMP);
-+  ff2s_check_flag(SET);
-+  ff2s_check_flag(NO_DEFAULT_VALUE);
-+  ff2s_check_flag(NUM);
-+  ff2s_check_flag(PART_KEY);
-+  ff2s_check_flag(GROUP);
-+  ff2s_check_flag(UNIQUE);
-+  ff2s_check_flag(BINCMP);
-+  ff2s_check_flag(ON_UPDATE_NOW);
-+#undef ff2s_check_flag
-+  if (f) sprintf(s, " unknows=0x%04x", f);
-+  return buf;
-+}
-+
-+static void print_field_types(MYSQL_RES *result) {
-+  MYSQL_FIELD *field;
-+  uint i = 0;
-+
-+  while ((field = mysql_fetch_field(result))) {
-+    tee_fprintf(PAGER,
-+                "Field %3u:  `%s`\n"
-+                "Catalog:    `%s`\n"
-+                "Database:   `%s`\n"
-+                "Table:      `%s`\n"
-+                "Org_table:  `%s`\n"
-+                "Type:       %s\n"
-+                "Collation:  %s (%u)\n"
-+                "Length:     %lu\n"
-+                "Max_length: %lu\n"
-+                "Decimals:   %u\n"
-+                "Flags:      %s\n\n",
-+                ++i, field->name, field->catalog, field->db, field->table,
-+                field->org_table, fieldtype2str(field->type),
-+                get_collation_name(field->charsetnr), field->charsetnr,
-+                field->length, field->max_length, field->decimals,
-+                fieldflags2str(field->flags));
-+  }
-+  tee_puts("", PAGER);
-+}
-+
-+/* Used to determine if we should invoke print_as_hex for this field */
-+
-+static bool is_binary_field(MYSQL_FIELD *field) {
-+  if ((field->charsetnr == 63) &&
-+      (field->type == MYSQL_TYPE_BIT || field->type == MYSQL_TYPE_BLOB ||
-+       field->type == MYSQL_TYPE_LONG_BLOB ||
-+       field->type == MYSQL_TYPE_MEDIUM_BLOB ||
-+       field->type == MYSQL_TYPE_TINY_BLOB ||
-+       field->type == MYSQL_TYPE_VAR_STRING ||
-+       field->type == MYSQL_TYPE_STRING || field->type == MYSQL_TYPE_VARCHAR ||
-+       field->type == MYSQL_TYPE_GEOMETRY))
-+    return true;
-+  return false;
-+}
-+
-+/* Print binary value as hex literal (0x ...) */
-+
-+static void print_as_hex(FILE *output_file, const char *str, ulong len,
-+                         ulong total_bytes_to_send) {
-+  const char *ptr = str, *end = ptr + len;
-+  ulong i;
-+
-+  if (str != nullptr) {
-+    fprintf(output_file, "0x");
-+    for (; ptr < end; ptr++)
-+      fprintf(output_file, "%02X",
-+              *(static_cast<const uchar *>(static_cast<const void *>(ptr))));
-+    /* Printed string length: two chars "0x" + two chars for each byte. */
-+    i = 2 + len * 2;
-+  } else {
-+    i = fprintf(output_file, "NULL");
-+  }
-+  for (; i < total_bytes_to_send; i++)
-+    tee_putc(static_cast<int>(' '), output_file);
-+}
-+
-+static void print_table_data(MYSQL_RES *result) {
-+  String separator(256);
-+  MYSQL_ROW cur;
-+  MYSQL_FIELD *field;
-+  bool *num_flag;
-+  size_t sz;
-+
-+  if (column_types_flag) {
-+    print_field_types(result);
-+    if (!mysql_num_rows(result)) return;
-+    mysql_field_seek(result, 0);
-+  }
-+  sz = sizeof(bool) * mysql_num_fields(result);
-+  num_flag = (bool *)my_safe_alloca(sz, MAX_ALLOCA_SIZE);
-+  separator.copy("+", 1, charset_info);
-+  while ((field = mysql_fetch_field(result))) {
-+    size_t length = column_names ? field->name_length : 0;
-+    if (quick)
-+      length = max<size_t>(length, field->length);
-+    else
-+      length = max<size_t>(length, field->max_length);
-+    if (length < 4 && !IS_NOT_NULL(field->flags))
-+      length = 4;  // Room for "NULL"
-+    if (opt_binhex && is_binary_field(field)) length = 2 + length * 2;
-+    field->max_length = (ulong)length;
-+    separator.fill(separator.length() + length + 2, '-');
-+    separator.append('+');
-+  }
-+  separator.append('\0');  // End marker for \0
-+  tee_puts(separator.ptr(), PAGER);
-+  if (column_names) {
-+    mysql_field_seek(result, 0);
-+    (void)tee_fputs("|", PAGER);
-+    for (uint off = 0; (field = mysql_fetch_field(result)); off++) {
-+      size_t name_length = strlen(field->name);
-+      size_t numcells = charset_info->cset->numcells(charset_info, field->name,
-+                                                     field->name + name_length);
-+      size_t display_length = field->max_length + name_length - numcells;
-+      tee_fprintf(PAGER, " %-*s |",
-+                  min<int>((int)display_length, MAX_COLUMN_LENGTH),
-+                  field->name);
-+      num_flag[off] = IS_NUM(field->type);
-+    }
-+    (void)tee_fputs("\n", PAGER);
-+    tee_puts(separator.ptr(), PAGER);
-+  }
-+
-+  while ((cur = mysql_fetch_row(result))) {
-+    ulong *lengths = mysql_fetch_lengths(result);
-+    (void)tee_fputs("| ", PAGER);
-+    mysql_field_seek(result, 0);
-+    for (uint off = 0; off < mysql_num_fields(result); off++) {
-+      const char *buffer;
-+      uint data_length;
-+      uint field_max_length;
-+      size_t visible_length;
-+      uint extra_padding;
-+
-+      if (off) (void)tee_fputs(" ", PAGER);
-+
-+      if (cur[off] == nullptr) {
-+        buffer = "NULL";
-+        data_length = 4;
-+      } else {
-+        buffer = cur[off];
-+        data_length = (uint)lengths[off];
-+      }
-+
-+      field = mysql_fetch_field(result);
-+      field_max_length = field->max_length;
-+
-+      /*
-+       How many text cells on the screen will this string span?  If it
-+       contains multibyte characters, then the number of characters we occupy
-+       on screen will be fewer than the number of bytes we occupy in memory.
-+
-+       We need to find how much screen real-estate we will occupy to know how
-+       many extra padding-characters we should send with the printing
-+       function.
-+      */
-+      visible_length = charset_info->cset->numcells(charset_info, buffer,
-+                                                    buffer + data_length);
-+      extra_padding = (uint)(data_length - visible_length);
-+
-+      if (opt_binhex && is_binary_field(field))
-+        print_as_hex(PAGER, cur[off], lengths[off], field_max_length);
-+      else if (field_max_length > MAX_COLUMN_LENGTH)
-+        tee_print_sized_data(buffer, data_length,
-+                             MAX_COLUMN_LENGTH + extra_padding, false);
-+      else {
-+        if (num_flag[off] != 0) /* if it is numeric, we right-justify it */
-+          tee_print_sized_data(buffer, data_length,
-+                               field_max_length + extra_padding, true);
-+        else
-+          tee_print_sized_data(buffer, data_length,
-+                               field_max_length + extra_padding, false);
-+      }
-+      tee_fputs(" |", PAGER);
-+    }
-+    (void)tee_fputs("\n", PAGER);
-+
-+    // Check interrupted_query last; this ensures that we get at least one
-+    // row. This is useful for aborted EXPLAIN ANALYZE queries.
-+    if (interrupted_query) break;
-+  }
-+  tee_puts(separator.ptr(), PAGER);
-+  my_safe_afree((bool *)num_flag, sz, MAX_ALLOCA_SIZE);
-+}
-+
-+/**
-+  Return the length of a field after it would be rendered into text.
-+
-+  This doesn't know or care about multibyte characters.  Assume we're
-+  using such a charset.  We can't know that all of the upcoming rows
-+  for this column will have bytes that each render into some fraction
-+  of a character.  It's at least possible that a row has bytes that
-+  all render into one character each, and so the maximum length is
-+  still the number of bytes.  (Assumption 1:  This can't be better
-+  because we can never know the number of characters that the DB is
-+  going to send -- only the number of bytes.  2: Chars <= Bytes.)
-+
-+  @param  field  Pointer to a field to be inspected
-+
-+  @returns  number of character positions to be used, at most
-+*/
-+static int get_field_disp_length(MYSQL_FIELD *field) {
-+  uint length = column_names ? field->name_length : 0;
-+
-+  if (quick)
-+    length = max<uint>(length, field->length);
-+  else
-+    length = max<uint>(length, field->max_length);
-+
-+  if (length < 4 && !IS_NOT_NULL(field->flags))
-+    length = 4; /* Room for "NULL" */
-+
-+  return length;
-+}
-+
-+/**
-+  For a new result, return the max number of characters that any
-+  upcoming row may return.
-+
-+  @param  result  Pointer to the result to judge
-+
-+  @returns  The max number of characters in any row of this result
-+*/
-+static int get_result_width(MYSQL_RES *result) {
-+  unsigned int len = 0;
-+  MYSQL_FIELD *field;
-+  MYSQL_FIELD_OFFSET offset;
-+
-+#ifndef NDEBUG
-+  offset = mysql_field_tell(result);
-+  assert(offset == 0);
-+#else
-+  offset = 0;
-+#endif
-+
-+  while ((field = mysql_fetch_field(result)) != nullptr)
-+    len +=
-+        get_field_disp_length(field) + 3; /* plus bar, space, & final space */
-+
-+  (void)mysql_field_seek(result, offset);
-+
-+  return len + 1; /* plus final bar. */
-+}
-+
-+static void tee_print_sized_data(const char *data, unsigned int data_length,
-+                                 unsigned int total_bytes_to_send,
-+                                 bool right_justified) {
-+  /*
-+    For '\0's print ASCII spaces instead, as '\0' is eaten by (at
-+    least my) console driver, and that messes up the pretty table
-+    grid.  (The \0 is also the reason we can't use fprintf() .)
-+  */
-+  unsigned int i;
-+
-+  if (right_justified)
-+    for (i = data_length; i < total_bytes_to_send; i++)
-+      tee_putc((int)' ', PAGER);
-+
-+  tee_write(PAGER, data, data_length, MY_PRINT_SPS_0 | MY_PRINT_MB);
-+
-+  if (!right_justified)
-+    for (i = data_length; i < total_bytes_to_send; i++)
-+      tee_putc((int)' ', PAGER);
-+}
-+
-+static void print_table_data_html(MYSQL_RES *result) {
-+  MYSQL_ROW cur;
-+  MYSQL_FIELD *field;
-+
-+  mysql_field_seek(result, 0);
-+  (void)tee_fputs("<TABLE BORDER=1><TR>", PAGER);
-+  if (column_names) {
-+    while ((field = mysql_fetch_field(result))) {
-+      tee_fputs("<TH>", PAGER);
-+      if (field->name && field->name[0])
-+        xmlencode_print(field->name, field->name_length);
-+      else
-+        tee_fputs(field->name ? " &nbsp; " : "NULL", PAGER);
-+      tee_fputs("</TH>", PAGER);
-+    }
-+    (void)tee_fputs("</TR>", PAGER);
-+  }
-+  while ((cur = mysql_fetch_row(result))) {
-+    if (interrupted_query) break;
-+    ulong *lengths = mysql_fetch_lengths(result);
-+    field = mysql_fetch_fields(result);
-+    (void)tee_fputs("<TR>", PAGER);
-+    for (uint i = 0; i < mysql_num_fields(result); i++) {
-+      (void)tee_fputs("<TD>", PAGER);
-+      if (opt_binhex && is_binary_field(&field[i]))
-+        print_as_hex(PAGER, cur[i], lengths[i], lengths[i]);
-+      else
-+        xmlencode_print(cur[i], lengths[i]);
-+      (void)tee_fputs("</TD>", PAGER);
-+    }
-+    (void)tee_fputs("</TR>", PAGER);
-+  }
-+  (void)tee_fputs("</TABLE>", PAGER);
-+}
-+
-+static void print_table_data_xml(MYSQL_RES *result) {
-+  MYSQL_ROW cur;
-+  MYSQL_FIELD *fields;
-+
-+  mysql_field_seek(result, 0);
-+
-+  tee_fputs("<?xml version=\"1.0\"?>\n\n<resultset statement=\"", PAGER);
-+  xmlencode_print(glob_buffer.ptr(), (int)strlen(glob_buffer.ptr()));
-+  tee_fputs("\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">",
-+            PAGER);
-+
-+  fields = mysql_fetch_fields(result);
-+  while ((cur = mysql_fetch_row(result))) {
-+    if (interrupted_query) break;
-+    ulong *lengths = mysql_fetch_lengths(result);
-+    (void)tee_fputs("\n  <row>\n", PAGER);
-+    for (uint i = 0; i < mysql_num_fields(result); i++) {
-+      tee_fprintf(PAGER, "\t<field name=\"");
-+      xmlencode_print(fields[i].name, (uint)strlen(fields[i].name));
-+      if (cur[i]) {
-+        tee_fprintf(PAGER, "\">");
-+        if (opt_binhex && is_binary_field(&fields[i]))
-+          print_as_hex(PAGER, cur[i], lengths[i], lengths[i]);
-+        else
-+          xmlencode_print(cur[i], lengths[i]);
-+        tee_fprintf(PAGER, "</field>\n");
-+      } else
-+        tee_fprintf(PAGER, "\" xsi:nil=\"true\" />\n");
-+    }
-+    (void)tee_fputs("  </row>\n", PAGER);
-+  }
-+  (void)tee_fputs("</resultset>\n", PAGER);
-+}
-+
-+static void print_table_data_vertically(MYSQL_RES *result) {
-+  MYSQL_ROW cur;
-+  uint max_length = 0;
-+  MYSQL_FIELD *field;
-+
-+  while ((field = mysql_fetch_field(result))) {
-+    uint length = field->name_length;
-+    if (length > max_length) max_length = length;
-+    field->max_length = length;
-+  }
-+
-+  mysql_field_seek(result, 0);
-+  for (uint row_count = 1; (cur = mysql_fetch_row(result)); row_count++) {
-+    if (interrupted_query) break;
-+    mysql_field_seek(result, 0);
-+    tee_fprintf(
-+        PAGER,
-+        "*************************** %d. row ***************************\n",
-+        row_count);
-+
-+    ulong *lengths = mysql_fetch_lengths(result);
-+
-+    for (uint off = 0; off < mysql_num_fields(result); off++) {
-+      field = mysql_fetch_field(result);
-+      if (column_names)
-+        tee_fprintf(PAGER, "%*s: ", (int)max_length, field->name);
-+      if (cur[off]) {
-+        if (opt_binhex && is_binary_field(field))
-+          print_as_hex(PAGER, cur[off], lengths[off], lengths[off]);
-+        else
-+          tee_write(PAGER, cur[off], lengths[off],
-+                    MY_PRINT_SPS_0 | MY_PRINT_MB);
-+        tee_putc('\n', PAGER);
-+      } else
-+        tee_fprintf(PAGER, "NULL\n");
-+    }
-+  }
-+}
-+
-+/* print_warnings should be called right after executing a statement */
-+
-+static void print_warnings() {
-+  const char *query;
-+  MYSQL_RES *result;
-+  MYSQL_ROW cur;
-+  uint64_t num_rows;
-+
-+  /* Save current error before calling "show warnings" */
-+  uint error = mysql_errno(&mysql);
-+
-+  /* Get the warnings */
-+  query = "show warnings";
-+  mysql_real_query_for_lazy(query, strlen(query));
-+  mysql_store_result_for_lazy(&result);
-+
-+  /* Bail out when no warnings */
-+  if (!result || !(num_rows = mysql_num_rows(result))) goto end;
-+
-+  cur = mysql_fetch_row(result);
-+
-+  /*
-+    Don't print a duplicate of the current error.  It is possible for SHOW
-+    WARNINGS to return multiple errors with the same code, but different
-+    messages.  To be safe, skip printing the duplicate only if it is the only
-+    warning.
-+  */
-+  if (!cur || (num_rows == 1 && error == (uint)strtoul(cur[1], nullptr, 10)))
-+    goto end;
-+
-+  /* Print the warnings */
-+  init_pager();
-+  do {
-+    tee_fprintf(PAGER, "%s (Code %s): %s\n", cur[0], cur[1], cur[2]);
-+  } while ((cur = mysql_fetch_row(result)));
-+  end_pager();
-+
-+end:
-+  mysql_free_result(result);
-+}
-+
-+static const char *array_value(const char **array, char key) {
-+  for (; *array; array += 2)
-+    if (**array == key) return array[1];
-+  return nullptr;
-+}
-+
-+static void xmlencode_print(const char *src, uint length) {
-+  if (!src)
-+    tee_fputs("NULL", PAGER);
-+  else
-+    tee_write(PAGER, src, length, MY_PRINT_XML | MY_PRINT_MB);
-+}
-+
-+static void safe_put_field(const char *pos, ulong length) {
-+  if (!pos)
-+    tee_fputs("NULL", PAGER);
-+  else {
-+    int flags =
-+        MY_PRINT_MB | (opt_raw_data ? 0 : (MY_PRINT_ESC_0 | MY_PRINT_CTRL));
-+    /* Can't use tee_fputs(), it stops with NUL characters. */
-+    tee_write(PAGER, pos, length, flags);
-+  }
-+}
-+
-+static void print_tab_data(MYSQL_RES *result) {
-+  MYSQL_ROW cur;
-+  MYSQL_FIELD *field;
-+  ulong *lengths;
-+
-+  if (opt_silent < 2 && column_names) {
-+    int first = 0;
-+    while ((field = mysql_fetch_field(result))) {
-+      if (first++) (void)tee_fputs("\t", PAGER);
-+      (void)tee_fputs(field->name, PAGER);
-+    }
-+    (void)tee_fputs("\n", PAGER);
-+  }
-+  while ((cur = mysql_fetch_row(result))) {
-+    lengths = mysql_fetch_lengths(result);
-+    field = mysql_fetch_fields(result);
-+    if (opt_binhex && is_binary_field(&field[0]))
-+      print_as_hex(PAGER, cur[0], lengths[0], lengths[0]);
-+    else
-+      safe_put_field(cur[0], lengths[0]);
-+    for (uint off = 1; off < mysql_num_fields(result); off++) {
-+      (void)tee_fputs("\t", PAGER);
-+      if (opt_binhex && field && is_binary_field(&field[off]))
-+        print_as_hex(PAGER, cur[off], lengths[off], lengths[off]);
-+      else
-+        safe_put_field(cur[off], lengths[off]);
-+    }
-+    (void)tee_fputs("\n", PAGER);
-+  }
-+}
-+
-+static int com_tee(String *buffer [[maybe_unused]],
-+                   char *line [[maybe_unused]]) {
-+  char file_name[FN_REFLEN], *end, *param;
-+
-+  while (my_isspace(charset_info, *line)) line++;
-+  if (!(param = strchr(line, ' ')))  // if outfile wasn't given, use the default
-+  {
-+    if (!strlen(outfile)) {
-+      printf("No previous outfile available, you must give a filename!\n");
-+      return 0;
-+    } else if (opt_outfile) {
-+      tee_fprintf(stdout, "Currently logging to file '%s'\n", outfile);
-+      return 0;
-+    } else
-+      param = outfile;  // resume using the old outfile
-+  }
-+
-+  /* eliminate the spaces before the parameters */
-+  while (my_isspace(charset_info, *param)) param++;
-+  end = strmake(file_name, param, sizeof(file_name) - 1);
-+  /* remove end space from command line */
-+  while (end > file_name && (my_isspace(charset_info, end[-1]) ||
-+                             my_iscntrl(charset_info, end[-1])))
-+    end--;
-+  end[0] = 0;
-+  if (end == file_name) {
-+    printf("No outfile specified!\n");
-+    return 0;
-+  }
-+  init_tee(file_name);
-+  return 0;
-+}
-+
-+static int com_notee(String *buffer [[maybe_unused]],
-+                     char *line [[maybe_unused]]) {
-+  if (opt_outfile) end_tee();
-+  tee_fprintf(stdout, "Outfile disabled.\n");
-+  return 0;
-+}
-+
-+/*
-+  Sorry, this command is not available in Windows.
-+*/
-+
-+#ifdef USE_POPEN
-+static int com_pager(String *buffer [[maybe_unused]],
-+                     char *line [[maybe_unused]]) {
-+  char pager_name[FN_REFLEN], *end, *param;
-+
-+  if (status.batch) return 0;
-+  /* Skip spaces in front of the pager command */
-+  while (my_isspace(charset_info, *line)) line++;
-+  /* Skip the pager command */
-+  param = strchr(line, ' ');
-+  /* Skip the spaces between the command and the argument */
-+  while (param && my_isspace(charset_info, *param)) param++;
-+  if (!param || !strlen(param))  // if pager was not given, use the default
-+  {
-+    if (!default_pager_set) {
-+      tee_fprintf(stdout, "Default pager wasn't set, using stdout.\n");
-+      opt_nopager = true;
-+      my_stpcpy(pager, "stdout");
-+      PAGER = stdout;
-+      return 0;
-+    }
-+    my_stpcpy(pager, default_pager);
-+  } else {
-+    end = strmake(pager_name, param, sizeof(pager_name) - 1);
-+    while (end > pager_name && (my_isspace(charset_info, end[-1]) ||
-+                                my_iscntrl(charset_info, end[-1])))
-+      end--;
-+    end[0] = 0;
-+    my_stpcpy(pager, pager_name);
-+    my_stpcpy(default_pager, pager_name);
-+  }
-+  opt_nopager = false;
-+  tee_fprintf(stdout, "PAGER set to '%s'\n", pager);
-+  return 0;
-+}
-+
-+static int com_nopager(String *buffer [[maybe_unused]],
-+                       char *line [[maybe_unused]]) {
-+  my_stpcpy(pager, "stdout");
-+  opt_nopager = true;
-+  PAGER = stdout;
-+  tee_fprintf(stdout, "PAGER set to stdout\n");
-+  return 0;
-+}
-+#endif
-+
-+/*
-+  Sorry, you can't send the result to an editor in Win32
-+*/
-+
-+#ifdef USE_POPEN
-+static int com_edit(String *buffer, char *line [[maybe_unused]]) {
-+  char filename[FN_REFLEN], buff[160];
-+  int fd, tmp;
-+  const char *editor;
-+
-+  if ((fd = create_temp_file(filename, NullS, "sql", O_CREAT | O_WRONLY,
-+                             KEEP_FILE, MYF(MY_WME))) < 0)
-+    goto err;
-+  if (buffer->is_empty() && !old_buffer.is_empty())
-+    (void)my_write(fd, (uchar *)old_buffer.ptr(), old_buffer.length(),
-+                   MYF(MY_WME));
-+  else
-+    (void)my_write(fd, (uchar *)buffer->ptr(), buffer->length(), MYF(MY_WME));
-+  (void)my_close(fd, MYF(0));
-+
-+  if (!(editor = (char *)getenv("EDITOR")) &&
-+      !(editor = (char *)getenv("VISUAL")))
-+    editor = "vi";
-+  strxmov(buff, editor, " ", filename, NullS);
-+  if (system(buff) == -1) goto err;
-+
-+  MY_STAT stat_arg;
-+  if (!my_stat(filename, &stat_arg, MYF(MY_WME))) goto err;
-+  if ((fd = my_open(filename, O_RDONLY, MYF(MY_WME))) < 0) goto err;
-+  (void)buffer->alloc((uint)stat_arg.st_size);
-+  if ((tmp = read(fd, buffer->ptr(), buffer->alloced_length())) >= 0L)
-+    buffer->length((uint)tmp);
-+  else
-+    buffer->length(0);
-+  (void)my_close(fd, MYF(0));
-+  (void)my_delete(filename, MYF(MY_WME));
-+err:
-+  return 0;
-+}
-+#endif
-+
-+/* If arg is given, exit without errors. This happens on command 'quit' */
-+
-+static int com_quit(String *buffer [[maybe_unused]],
-+                    char *line [[maybe_unused]]) {
-+  status.exit_status = 0;
-+  return 1;
-+}
-+
-+static int com_rehash(String *buffer [[maybe_unused]],
-+                      char *line [[maybe_unused]]) {
-+#ifdef HAVE_READLINE
-+  build_completion_hash(true, false);
-+#endif
-+  return 0;
-+}
-+
-+static int com_shell(String *buffer [[maybe_unused]],
-+                     char *line [[maybe_unused]]) {
-+  char *shell_cmd;
-+
-+  /* Skip space from line begin */
-+  while (my_isspace(charset_info, *line)) line++;
-+  if (!(shell_cmd = strchr(line, ' '))) {
-+    put_info("Usage: \\! shell-command", INFO_ERROR);
-+    return -1;
-+  }
-+
-+  if (!opt_system_command) {
-+    return put_info(
-+        "'system' command received, but the --system-command option is off. "
-+        "Skipping.",
-+        INFO_ERROR);
-+  }
-+  /*
-+    The output of the shell command does not
-+    get directed to the pager or the outfile
-+  */
-+  if (system(shell_cmd) == -1) {
-+    put_info(strerror(errno), INFO_ERROR, errno);
-+    return -1;
-+  }
-+  return 0;
-+}
-+
-+static int com_print(String *buffer, char *line [[maybe_unused]]) {
-+  tee_puts("--------------", stdout);
-+  (void)tee_fputs(buffer->c_ptr(), stdout);
-+  if (!buffer->length() || (*buffer)[buffer->length() - 1] != '\n')
-+    tee_putc('\n', stdout);
-+  tee_puts("--------------\n", stdout);
-+  return 0; /* If empty buffer */
-+}
-+
-+/* ARGSUSED */
-+static int com_connect(String *buffer, char *line) {
-+  char *tmp, buff[256];
-+  bool save_rehash = opt_rehash;
-+  int error;
-+
-+  memset(buff, 0, sizeof(buff));
-+  if (buffer) {
-+    /*
-+      Two null bytes are needed in the end of buff to allow
-+      get_arg to find end of string the second time it's called.
-+    */
-+    tmp = strmake(buff, line, sizeof(buff) - 2);
-+#ifdef EXTRA_DEBUG
-+    tmp[1] = 0;
-+#endif
-+    tmp = get_arg(buff, false);
-+    if (tmp && *tmp) {
-+      my_free(current_db);
-+      current_db = my_strdup(PSI_NOT_INSTRUMENTED, tmp, MYF(MY_WME));
-+      tmp = get_arg(buff, true);
-+      if (tmp) {
-+        my_free(current_host);
-+        current_host = my_strdup(PSI_NOT_INSTRUMENTED, tmp, MYF(MY_WME));
-+        my_free(dns_srv_name);
-+        dns_srv_name = nullptr;
-+      }
-+    } else {
-+      /* Quick re-connect */
-+      opt_rehash = false; /* purecov: tested */
-+    }
-+    buffer->length(0);  // command used
-+  } else
-+    opt_rehash = false;
-+  error = sql_connect(current_host, current_db, current_user, 0);
-+  opt_rehash = save_rehash;
-+
-+  if (connected) {
-+    sprintf(buff, "Connection id:    %lu", mysql_thread_id(&mysql));
-+    put_info(buff, INFO_INFO);
-+    sprintf(buff, "Current database: %.128s\n",
-+            current_db ? current_db : "*** NONE ***");
-+    put_info(buff, INFO_INFO);
-+  }
-+  return error;
-+}
-+
-+static int com_source(String *buffer [[maybe_unused]], char *line) {
-+  char source_name[FN_REFLEN], *end, *param;
-+  LINE_BUFFER *line_buff;
-+  int error;
-+  STATUS old_status;
-+  FILE *sql_file;
-+
-+  /* Skip space from file name */
-+  while (my_isspace(charset_info, *line)) line++;
-+  if (!(param = strchr(line, ' ')))  // Skip command name
-+    return put_info("Usage: \\. <filename> | source <filename>", INFO_ERROR, 0);
-+  while (my_isspace(charset_info, *param)) param++;
-+  end = strmake(source_name, param, sizeof(source_name) - 1);
-+  while (end > source_name && (my_isspace(charset_info, end[-1]) ||
-+                               my_iscntrl(charset_info, end[-1])))
-+    end--;
-+  end[0] = 0;
-+  unpack_filename(source_name, source_name);
-+  /* open file name */
-+  if (!(sql_file = my_fopen(source_name, O_RDONLY | MY_FOPEN_BINARY, MYF(0)))) {
-+    char buff[FN_REFLEN + 60];
-+    sprintf(buff, "Failed to open file '%s', error: %d", source_name, errno);
-+    return put_info(buff, INFO_ERROR, 0);
-+  }
-+
-+  if (!(line_buff = batch_readline_init(MAX_BATCH_BUFFER_SIZE, sql_file))) {
-+    my_fclose(sql_file, MYF(0));
-+    return put_info("Can't initialize batch_readline", INFO_ERROR, 0);
-+  }
-+
-+  /* Save old status */
-+  old_status = status;
-+  memset(&status, 0, sizeof(status));
-+
-+  status.batch = old_status.batch;  // Run in batch mode
-+  status.line_buff = line_buff;
-+  status.file_name = source_name;
-+  glob_buffer.length(0);  // Empty command buffer
-+  error = read_and_execute(false);
-+  status = old_status;  // Continue as before
-+  my_fclose(sql_file, MYF(0));
-+  batch_readline_end(line_buff);
-+  return error;
-+}
-+
-+/* ARGSUSED */
-+static int com_delimiter(String *buffer [[maybe_unused]], char *line) {
-+  char buff[256], *tmp;
-+
-+  strmake(buff, line, sizeof(buff) - 1);
-+  tmp = get_arg(buff, false);
-+
-+  if (!tmp || !*tmp) {
-+    put_info("DELIMITER must be followed by a 'delimiter' character or string",
-+             INFO_ERROR);
-+    return 0;
-+  } else {
-+    if (strstr(tmp, "\\")) {
-+      put_info("DELIMITER cannot contain a backslash character", INFO_ERROR);
-+      return 0;
-+    }
-+  }
-+  strmake(delimiter, tmp, sizeof(delimiter) - 1);
-+  delimiter_length = (int)strlen(delimiter);
-+  delimiter_str = delimiter;
-+  return 0;
-+}
-+
-+/* ARGSUSED */
-+static int com_use(String *buffer [[maybe_unused]], char *line) {
-+  char *tmp, buff[FN_REFLEN + 1];
-+  int select_db;
-+  uint warnings;
-+
-+  memset(buff, 0, sizeof(buff));
-+
-+  /*
-+    In case of quotes used, try to get the normalized db name.
-+  */
-+  if (get_quote_count(line) > 0) {
-+    if (normalize_dbname(line, buff, sizeof(buff))) return put_error(&mysql);
-+    tmp = buff;
-+  } else {
-+    strmake(buff, line, sizeof(buff) - 1);
-+    tmp = get_arg(buff, false);
-+  }
-+
-+  if (!tmp || !*tmp) {
-+    put_info("USE must be followed by a database name", INFO_ERROR);
-+    return 0;
-+  }
-+  /*
-+    We need to recheck the current database, because it may change
-+    under our feet, for example if DROP DATABASE or RENAME DATABASE
-+    (latter one not yet available by the time the comment was written)
-+    If this command fails we assume we lost connection.
-+  */
-+  if (get_current_db()) connected = false;
-+
-+  if (!current_db || cmp_database(charset_info, current_db, tmp)) {
-+    if (one_database) {
-+      skip_updates = true;
-+      select_db = 0;  // don't do mysql_select_db()
-+    } else
-+      select_db = 2;  // do mysql_select_db() and build_completion_hash()
-+  } else {
-+    /*
-+      USE to the current db specified.
-+      We do need to send mysql_select_db() to make server
-+      update database level privileges, which might
-+      change since last USE (see bug#10979).
-+      For performance purposes, we'll skip rebuilding of completion hash.
-+    */
-+    skip_updates = false;
-+    select_db = 1;  // do only mysql_select_db(), without completion
-+  }
-+
-+  if (select_db) {
-+    /*
-+      reconnect once if connection is down or if connection was found to
-+      be down during query
-+    */
-+    if (!connected && reconnect())
-+      return opt_reconnect ? -1 : 1;  // Fatal error
-+    if (mysql_select_db(&mysql, tmp)) {
-+      if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR) return put_error(&mysql);
-+
-+      if (reconnect()) return opt_reconnect ? -1 : 1;  // Fatal error
-+      if (mysql_select_db(&mysql, tmp)) return put_error(&mysql);
-+    }
-+    my_free(current_db);
-+    current_db = my_strdup(PSI_NOT_INSTRUMENTED, tmp, MYF(MY_WME));
-+#ifdef HAVE_READLINE
-+    if (select_db > 1) build_completion_hash(opt_rehash, true);
-+#endif
-+  }
-+
-+  if (0 < (warnings = mysql_warning_count(&mysql))) {
-+    snprintf(buff, sizeof(buff), "Database changed, %u warning%s", warnings,
-+             warnings > 1 ? "s" : "");
-+    put_info(buff, INFO_INFO);
-+    if (show_warnings == 1) print_warnings();
-+  } else
-+    put_info("Database changed", INFO_INFO);
-+  return 0;
-+}
-+
-+/**
-+  Normalize database name.
-+
-+  @param [in] line           The command.
-+  @param [out] buff          Normalized db name.
-+  @param [in] buff_size      Buffer size.
-+
-+  @return Operation status
-+      @retval 0    Success
-+      @retval 1    Failure
-+
-+  @note Sometimes server normalizes the database names
-+        & APIs like mysql_select_db() expect normalized
-+        database names. Since it is difficult to perform
-+        the name conversion/normalization on the client
-+        side, this function tries to get the normalized
-+        dbname (indirectly) from the server.
-+*/
-+
-+static int normalize_dbname(const char *line, char *buff, uint buff_size) {
-+  MYSQL_RES *res = nullptr;
-+
-+  /* Send the "USE db" command to the server. */
-+  if (mysql_query(&mysql, line)) return 1;
-+
-+  /*
-+    Now, get the normalized database name and store it
-+    into the buff.
-+  */
-+  if (!mysql_query(&mysql, "SELECT DATABASE()") &&
-+      (res = mysql_use_result(&mysql))) {
-+    MYSQL_ROW row = mysql_fetch_row(res);
-+    if (row && row[0]) {
-+      size_t len = strlen(row[0]);
-+      /* Make sure there is enough room to store the dbname. */
-+      if ((len > buff_size) || !memcpy(buff, row[0], len)) {
-+        mysql_free_result(res);
-+        return 1;
-+      }
-+    }
-+    mysql_free_result(res);
-+  }
-+
-+  /* Restore the original database. */
-+  if (current_db && mysql_select_db(&mysql, current_db)) return 1;
-+
-+  return 0;
-+}
-+
-+static int com_warnings(String *buffer [[maybe_unused]],
-+                        char *line [[maybe_unused]]) {
-+  show_warnings = true;
-+  put_info("Show warnings enabled.", INFO_INFO);
-+  return 0;
-+}
-+
-+static int com_nowarnings(String *buffer [[maybe_unused]],
-+                          char *line [[maybe_unused]]) {
-+  show_warnings = false;
-+  put_info("Show warnings disabled.", INFO_INFO);
-+  return 0;
-+}
-+
-+static int com_query_attributes(String *buffer [[maybe_unused]], char *line) {
-+  char buff[1024], *param, name[1024];
-+  memset(buff, 0, sizeof(buff));
-+  strmake(buff, line, sizeof(buff) - 1);
-+  param = buff;
-+  global_attrs->clear(connected ? &mysql : nullptr);
-+  do {
-+    param = get_arg(param, param != buff);
-+    if (!param || !*param) break;
-+
-+    strncpy(name, param, sizeof(name) - 1);
-+    param = get_arg(param, true);
-+    if (!param || !*param) {
-+      return put_info("Usage: query_attributes name1 value1 name2 value2 ...",
-+                      INFO_ERROR, 0);
-+    }
-+
-+    if (global_attrs->push_param(name, param))
-+      return put_info("Failed to push a parameter", INFO_ERROR, 0);
-+  } while (param != nullptr);
-+  return 0;
-+}
-+
-+static int com_ssl_session_data_print(String *buffer [[maybe_unused]],
-+                                      char *line) {
-+  char msgbuf[256];
-+  char *param = get_arg(line, false);
-+  const char *err_text = nullptr;
-+  FILE *fo = nullptr;
-+  void *data = nullptr;
-+
-+  if (param) {
-+    if (nullptr == (fo = fopen(param, "w"))) {
-+      err_text = "Failed to open the output file";
-+      goto end;
-+    }
-+  } else
-+    fo = stdout;
-+
-+  data = mysql_get_ssl_session_data(&mysql, 0, nullptr);
-+  if (!data) {
-+    err_text = nullptr;
-+    put_error(&mysql);
-+    goto end;
-+  }
-+  if (0 > fputs(reinterpret_cast<char *>(data), fo)) {
-+    snprintf(msgbuf, sizeof(msgbuf), "Write of session data failed: %d (%s)",
-+             errno, strerror(errno));
-+    err_text = &msgbuf[0];
-+    goto end;
-+  }
-+  if (fo == stdout) fputs("\n", fo);
-+
-+end:
-+  if (data) mysql_free_ssl_session_data(&mysql, data);
-+  if (fo && fo != stdout) fclose(fo);
-+  if (err_text) return put_info(err_text, INFO_ERROR);
-+  return 0;
-+}
-+
-+/*
-+  Gets argument from a command on the command line. If get_next_arg is
-+  not defined, skips the command and returns the first argument. The
-+  line is modified by adding zero to the end of the argument. If
-+  get_next_arg is defined, then the function searches for end of string
-+  first, after found, returns the next argument and adds zero to the
-+  end. If you ever wish to use this feature, remember to initialize all
-+  items in the array to zero first.
-+*/
-+
-+char *get_arg(char *line, bool get_next_arg) {
-+  char *ptr, *start;
-+  bool quoted = false, valid_arg = false;
-+  char qtype = 0;
-+
-+  ptr = line;
-+  if (get_next_arg) {
-+    for (; *ptr; ptr++)
-+      ;
-+    if (*(ptr + 1)) ptr++;
-+  } else {
-+    /* skip leading white spaces */
-+    while (my_isspace(charset_info, *ptr)) ptr++;
-+    if (*ptr == '\\')  // short command was used
-+      ptr += 2;
-+    else
-+      while (*ptr && !my_isspace(charset_info, *ptr))  // skip command
-+        ptr++;
-+  }
-+  if (!*ptr) return NullS;
-+  while (my_isspace(charset_info, *ptr)) ptr++;
-+  if (*ptr == '\'' || *ptr == '\"' || *ptr == '`') {
-+    qtype = *ptr;
-+    quoted = true;
-+    ptr++;
-+  }
-+  for (start = ptr; *ptr; ptr++) {
-+    // if it is a quoted string do not remove backslash
-+    if (!quoted && *ptr == '\\' && ptr[1])  // escaped character
-+    {
-+      // Remove the backslash
-+      my_stpmov(ptr, ptr + 1);
-+    } else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype)) {
-+      *ptr = 0;
-+      break;
-+    }
-+  }
-+  valid_arg = ptr != start;
-+  return valid_arg ? start : NullS;
-+}
-+
-+/*
-+  Number of quotes present in the command's argument.
-+*/
-+static int get_quote_count(const char *line) {
-+  int quote_count = 0;
-+  const char *quote = line;
-+
-+  while ((quote = strpbrk(quote, "'`\"")) != nullptr) {
-+    quote_count++;
-+    quote++;
-+  }
-+
-+  return quote_count;
-+}
-+
-+static int sql_real_connect(char *host, char *database, char *user, char *,
-+                            uint silent) {
-+  if (connected) {
-+    connected = false;
-+#ifdef HAVE_SETNS
-+    if (opt_network_namespace) (void)release_network_namespace_resources();
-+#endif
-+    mysql_close(&mysql);
-+  }
-+
-+  mysql_init(&mysql);
-+  if (init_connection_options(&mysql)) {
-+    put_error_if_any(&mysql);
-+    (void)fflush(stdout);
-+    return ignore_errors ? -1 : 1;
-+  }
-+#ifdef _WIN32
-+  uint cnv_errors;
-+  String converted_database, converted_user;
-+  if (!my_charset_same(&my_charset_utf8mb4_bin, mysql.charset)) {
-+    /* Convert user and database from UTF8MB4 to connection character set */
-+    if (user) {
-+      converted_user.copy(user, strlen(user) + 1, &my_charset_utf8mb4_bin,
-+                          mysql.charset, &cnv_errors);
-+      user = (char *)converted_user.ptr();
-+    }
-+    if (database) {
-+      converted_database.copy(database, strlen(database) + 1,
-+                              &my_charset_utf8mb4_bin, mysql.charset,
-+                              &cnv_errors);
-+      database = (char *)converted_database.ptr();
-+    }
-+  }
-+#endif
-+
-+#ifdef HAVE_SETNS
-+  if (opt_network_namespace && set_network_namespace(opt_network_namespace)) {
-+    if (!silent) {
-+      char msgbuf[PATH_MAX];
-+      snprintf(msgbuf, sizeof(msgbuf), "Network namespace error: %s",
-+               strerror(errno));
-+      put_info(msgbuf, INFO_ERROR);
-+    }
-+
-+    return ignore_errors ? -1 : 1;  // Abort
-+  }
-+#endif
-+  MYSQL *ret;
-+  if (dns_srv_name)
-+    ret = mysql_real_connect_dns_srv(&mysql, dns_srv_name, user, nullptr,
-+                                     database,
-+                                     connect_flag | CLIENT_MULTI_STATEMENTS);
-+  else
-+    ret = mysql_real_connect(&mysql, host, user, nullptr, database,
-+                             opt_mysql_port, opt_mysql_unix_port,
-+                             connect_flag | CLIENT_MULTI_STATEMENTS);
-+  if (!ret) {
-+#ifdef HAVE_SETNS
-+    if (opt_network_namespace) (void)restore_original_network_namespace();
-+#endif
-+    if (mysql_errno(&mysql) == ER_MUST_CHANGE_PASSWORD_LOGIN) {
-+      tee_fprintf(stdout,
-+                  "Please use --connect-expired-password option or "
-+                  "invoke mysql in interactive mode.\n");
-+      return ignore_errors ? -1 : 1;
-+    }
-+    if (!silent || (mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&
-+                    mysql_errno(&mysql) != CR_CONNECTION_ERROR)) {
-+      (void)put_error(&mysql);
-+      (void)fflush(stdout);
-+      return ignore_errors ? -1 : 1;  // Abort
-+    }
-+    return -1;  // Retryable
-+  }
-+
-+  /* do user registration */
-+  if (opt_fido_register_factor) {
-+    char errmsg[FN_REFLEN];
-+    if (user_device_registration(&mysql, opt_fido_register_factor, errmsg)) {
-+      put_info(errmsg, INFO_ERROR);
-+      return 1;
-+    }
-+  }
-+
-+#ifdef HAVE_SETNS
-+  if (opt_network_namespace && restore_original_network_namespace()) {
-+    if (!silent) {
-+      char msgbuf[PATH_MAX];
-+      snprintf(msgbuf, sizeof(msgbuf), "Network namespace error: %s",
-+               strerror(errno));
-+      put_info(msgbuf, INFO_ERROR);
-+    }
-+
-+    return ignore_errors ? -1 : 1;  // Abort
-+  }
-+#endif
-+
-+  if (ssl_client_check_post_connect_ssl_setup(
-+          &mysql, [](const char *err) { put_info(err, INFO_ERROR); }))
-+    return 1;
-+
-+  void *new_ssl_session_data = mysql_get_ssl_session_data(&mysql, 0, nullptr);
-+  if (new_ssl_session_data != nullptr) {
-+    if (ssl_session_data != nullptr)
-+      mysql_free_ssl_session_data(&mysql, ssl_session_data);
-+    ssl_session_data = new_ssl_session_data;
-+  } else {
-+    DBUG_PRINT("error", ("unable to save SSL session"));
-+  }
-+#ifdef _WIN32
-+  /* Convert --execute buffer from UTF8MB4 to connection character set */
-+  if (!execute_buffer_conversion_done && status.line_buff &&
-+      !status.line_buff->file && /* Convert only -e buffer, not real file */
-+      status.line_buff->buffer < status.line_buff->end && /* Non-empty */
-+      !my_charset_same(&my_charset_utf8mb4_bin, mysql.charset)) {
-+    String tmp;
-+    size_t len = status.line_buff->end - status.line_buff->buffer;
-+    uint dummy_errors;
-+    /*
-+      Don't convert trailing '\n' character - it was appended during
-+      last batch_readline_command() call.
-+      Otherwise we'll get an extra line, which makes some tests fail.
-+    */
-+    if (status.line_buff->buffer[len - 1] == '\n') len--;
-+    if (tmp.copy(status.line_buff->buffer, len, &my_charset_utf8mb4_bin,
-+                 mysql.charset, &dummy_errors))
-+      return 1;
-+
-+    /* Free the old line buffer */
-+    batch_readline_end(status.line_buff);
-+
-+    /* Re-initialize line buffer from the converted string */
-+    if (!(status.line_buff = batch_readline_command(nullptr, tmp.c_ptr_safe())))
-+      return 1;
-+  }
-+  execute_buffer_conversion_done = true;
-+#endif /* _WIN32 */
-+
-+  charset_info = mysql.charset;
-+
-+  connected = true;
-+  mysql.reconnect = debug_info_flag;  // We want to know if this happens
-+#ifdef HAVE_READLINE
-+  build_completion_hash(opt_rehash, true);
-+#endif
-+  return 0;
-+}
-+
-+/* Initialize options for the given connection handle. */
-+static bool init_connection_options(MYSQL *mysql) {
-+  bool handle_expired = (opt_connect_expired_password || !status.batch);
-+
-+  if (opt_init_command)
-+    mysql_options(mysql, MYSQL_INIT_COMMAND, opt_init_command);
-+
-+  if (opt_connect_timeout) {
-+    uint timeout = opt_connect_timeout;
-+    mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&timeout);
-+  }
-+
-+  if (opt_bind_addr) mysql_options(mysql, MYSQL_OPT_BIND, opt_bind_addr);
-+
-+  if (opt_compress) mysql_options(mysql, MYSQL_OPT_COMPRESS, NullS);
-+  if (opt_compress_algorithm)
-+    mysql_options(mysql, MYSQL_OPT_COMPRESSION_ALGORITHMS,
-+                  opt_compress_algorithm);
-+
-+  mysql_options(mysql, MYSQL_OPT_ZSTD_COMPRESSION_LEVEL,
-+                &opt_zstd_compress_level);
-+
-+  if (using_opt_local_infile)
-+    mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, (char *)&opt_local_infile);
-+
-+  if (SSL_SET_OPTIONS(mysql)) {
-+    tee_fprintf(stdout, "%s", SSL_SET_OPTIONS_ERROR);
-+    return true;
-+  }
-+
-+  if (ssl_session_data)
-+    mysql_options(mysql, MYSQL_OPT_SSL_SESSION_DATA, ssl_session_data);
-+
-+  if (opt_protocol)
-+    mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char *)&opt_protocol);
-+
-+#if defined(_WIN32)
-+  if (shared_memory_base_name)
-+    mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
-+                  shared_memory_base_name);
-+#endif
-+
-+  if (safe_updates) {
-+    char init_command[100];
-+    sprintf(init_command,
-+            "SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=%lu,MAX_JOIN_SIZE=%lu",
-+            select_limit, max_join_size);
-+    mysql_options(mysql, MYSQL_INIT_COMMAND, init_command);
-+  }
-+
-+  if (mysql_set_character_set(mysql, default_charset)) return true;
-+
-+  if (opt_plugin_dir && *opt_plugin_dir)
-+    mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
-+
-+  if (opt_load_data_local_dir &&
-+      mysql_options(mysql, MYSQL_OPT_LOAD_DATA_LOCAL_DIR,
-+                    opt_load_data_local_dir))
-+    return true;
-+
-+  if (opt_default_auth && *opt_default_auth)
-+    mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
-+
-+  set_server_public_key(mysql);
-+
-+  set_get_server_public_key_option(mysql);
-+
-+  if (using_opt_enable_cleartext_plugin)
-+    mysql_options(mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
-+                  (char *)&opt_enable_cleartext_plugin);
-+
-+  mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, nullptr);
-+  mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "mysql");
-+  if (current_os_user)
-+    mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "os_user",
-+                   current_os_user);
-+  if (current_os_sudouser)
-+    mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "os_sudouser",
-+                   current_os_sudouser);
-+
-+  mysql_options(mysql, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, &handle_expired);
-+
-+  set_password_options(mysql);
-+
-+  struct st_mysql_client_plugin *oci_iam_plugin = mysql_client_find_plugin(
-+      mysql, "authentication_oci_client", MYSQL_CLIENT_AUTHENTICATION_PLUGIN);
-+
-+  /* set authentication_oci_client config profile option if required */
-+  if (opt_authentication_oci_client_config_profile != nullptr) {
-+    if (!oci_iam_plugin) {
-+      put_info("Cannot load the authentication_oci_client plugin.", INFO_ERROR);
-+      return true;
-+    }
-+    if (mysql_plugin_options(oci_iam_plugin,
-+                             "authentication-oci-client-config-profile",
-+                             opt_authentication_oci_client_config_profile)) {
-+      put_info(
-+          "Failed to set config profile for authentication_oci_client "
-+          "plugin.",
-+          INFO_ERROR);
-+      return true;
-+    }
-+  }
-+  /* set OCI config file option if required */
-+  if (opt_oci_config_file != nullptr) {
-+    if (!oci_iam_plugin) {
-+      put_info("Cannot load the authentication_oci_client plugin.", INFO_ERROR);
-+      return true;
-+    }
-+    if (mysql_plugin_options(oci_iam_plugin, "oci-config-file",
-+                             opt_oci_config_file)) {
-+      put_info(
-+          "Failed to set config file for authentication_oci_client plugin.",
-+          INFO_ERROR);
-+      return true;
-+    }
-+  }
-+
-+#if defined(_WIN32)
-+  char error[256]{0};
-+  if (set_authentication_kerberos_client_mode(mysql, error, 255)) {
-+    put_info(error, INFO_ERROR);
-+    return 1;
-+  }
-+#endif
-+
-+  return false;
-+}
-+
-+static int sql_connect(char *host, char *database, char *user, uint silent) {
-+  bool message = false;
-+  uint count = 0;
-+  int error;
-+  for (;;) {
-+    if ((error = sql_real_connect(host, database, user, nullptr, wait_flag)) >=
-+        0) {
-+      if (count) {
-+        tee_fputs("\n", stderr);
-+        (void)fflush(stderr);
-+      }
-+      return error;
-+    }
-+    if (!wait_flag) return ignore_errors ? -1 : 1;
-+    if (!message && !silent) {
-+      message = true;
-+      tee_fputs("Waiting", stderr);
-+      (void)fflush(stderr);
-+    }
-+    (void)sleep(wait_time);
-+    if (!silent) {
-+      putc('.', stderr);
-+      (void)fflush(stderr);
-+      count++;
-+    }
-+  }
-+}
-+
-+static int com_status(String *buffer [[maybe_unused]],
-+                      char *line [[maybe_unused]]) {
-+  const char *status_str;
-+  char buff[40];
-+  ulonglong id;
-+  MYSQL_RES *result = nullptr;
-+
-+  if (mysql_real_query_for_lazy(
-+          STRING_WITH_LEN("select DATABASE(), USER() limit 1")))
-+    return 0;
-+
-+  tee_puts("--------------", stdout);
-+  usage(1); /* Print version */
-+  tee_fprintf(stdout, "\nConnection id:\t\t%lu\n", mysql_thread_id(&mysql));
-+  /*
-+    Don't remove "limit 1",
-+    it is protection against SQL_SELECT_LIMIT=0
-+  */
-+  if (!mysql_store_result_for_lazy(&result)) {
-+    MYSQL_ROW cur = mysql_fetch_row(result);
-+    if (cur) {
-+      tee_fprintf(stdout, "Current database:\t%s\n", cur[0] ? cur[0] : "");
-+      tee_fprintf(stdout, "Current user:\t\t%s\n", cur[1]);
-+    }
-+    mysql_free_result(result);
-+  }
-+
-+  if ((status_str = mysql_get_ssl_cipher(&mysql)))
-+    tee_fprintf(stdout, "SSL:\t\t\tCipher in use is %s\n", status_str);
-+  else
-+    tee_puts("SSL:\t\t\tNot in use", stdout);
-+
-+  if (skip_updates) {
-+    tee_fprintf(stdout, "\nAll updates ignored to this database\n");
-+  }
-+#ifdef USE_POPEN
-+  tee_fprintf(stdout, "Current pager:\t\t%s\n", pager);
-+  tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : "");
-+#endif
-+  tee_fprintf(stdout, "Using delimiter:\t%s\n", delimiter);
-+  tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&mysql));
-+  tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql));
-+  tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql));
-+  if ((id = mysql_insert_id(&mysql)))
-+    tee_fprintf(stdout, "Insert id:\t\t%s\n", llstr(id, buff));
-+
-+  /* "limit 1" is protection against SQL_SELECT_LIMIT=0 */
-+  if (mysql_real_query_for_lazy(STRING_WITH_LEN(
-+          "select @@character_set_client, @@character_set_connection, "
-+          "@@character_set_server, @@character_set_database limit 1"))) {
-+    if (mysql_errno(&mysql) == CR_SERVER_GONE_ERROR) return 0;
-+  }
-+  if (!mysql_store_result_for_lazy(&result)) {
-+    MYSQL_ROW cur = mysql_fetch_row(result);
-+    if (cur) {
-+      tee_fprintf(stdout, "Server characterset:\t%s\n", cur[2] ? cur[2] : "");
-+      tee_fprintf(stdout, "Db     characterset:\t%s\n", cur[3] ? cur[3] : "");
-+      tee_fprintf(stdout, "Client characterset:\t%s\n", cur[0] ? cur[0] : "");
-+      tee_fprintf(stdout, "Conn.  characterset:\t%s\n", cur[1] ? cur[1] : "");
-+    }
-+    mysql_free_result(result);
-+  } else {
-+    /* Probably pre-4.1 server */
-+    tee_fprintf(stdout, "Client characterset:\t%s\n", charset_info->csname);
-+    tee_fprintf(stdout, "Server characterset:\t%s\n", mysql.charset->csname);
-+  }
-+
-+  if (strstr(mysql_get_host_info(&mysql), "TCP/IP") || !mysql.unix_socket)
-+    tee_fprintf(stdout, "TCP port:\t\t%d\n", mysql.port);
-+  else
-+    tee_fprintf(stdout, "UNIX socket:\t\t%s\n", mysql.unix_socket);
-+  if (mysql.net.compress) tee_fprintf(stdout, "Protocol:\t\tCompressed\n");
-+  if (opt_binhex) tee_fprintf(stdout, "Binary data as:\t\tHexadecimal\n");
-+  if (mysql_get_ssl_session_reused(&mysql))
-+    tee_fprintf(stdout, "SSL session reused:\ttrue\n");
-+
-+  if ((status_str = mysql_stat(&mysql)) && !mysql_error(&mysql)[0]) {
-+    ulong sec;
-+    const char *pos = strchr(status_str, ' ');
-+    /* print label */
-+    tee_fprintf(stdout, "%.*s\t\t\t", (int)(pos - status_str), status_str);
-+    if ((status_str = str2int(pos, 10, 0, LONG_MAX, (long *)&sec))) {
-+      nice_time((double)sec, buff, false);
-+      tee_puts(buff, stdout);                  /* print nice time */
-+      while (*status_str == ' ') status_str++; /* to next info */
-+      tee_putc('\n', stdout);
-+      tee_puts(status_str, stdout);
-+    }
-+  }
-+  if (safe_updates) {
-+    tee_fprintf(stdout, "\nNote that you are running in safe_update_mode:\n");
-+    tee_fprintf(stdout,
-+                "\
-+UPDATEs and DELETEs that don't use a key in the WHERE clause are not allowed.\n\
-+(One can force an UPDATE/DELETE by adding LIMIT # at the end of the command.)\n\
-+SELECT has an automatic 'LIMIT %lu' if LIMIT is not used.\n\
-+Max number of examined row combination in a join is set to: %lu\n\n",
-+                select_limit, max_join_size);
-+  }
-+  tee_puts("--------------\n", stdout);
-+  return 0;
-+}
-+
-+static const char *server_version_string(MYSQL *con) {
-+  /* Only one thread calls this, so no synchronization is needed */
-+  if (server_version == nullptr) {
-+    MYSQL_RES *result;
-+
-+    /* "limit 1" is protection against SQL_SELECT_LIMIT=0 */
-+    if (!mysql_query(con, "select @@version_comment limit 1") &&
-+        (result = mysql_use_result(con))) {
-+      MYSQL_ROW cur = mysql_fetch_row(result);
-+      if (cur && cur[0]) {
-+        /* version, space, comment, \0 */
-+        size_t len = strlen(mysql_get_server_info(con)) + strlen(cur[0]) + 2;
-+
-+        if ((server_version =
-+                 (char *)my_malloc(PSI_NOT_INSTRUMENTED, len, MYF(MY_WME)))) {
-+          char *bufp;
-+          bufp = my_stpcpy(server_version, mysql_get_server_info(con));
-+          bufp = my_stpcpy(bufp, " ");
-+          (void)my_stpcpy(bufp, cur[0]);
-+        }
-+      }
-+      mysql_free_result(result);
-+    }
-+
-+    /*
-+      If for some reason we didn't get a version_comment, we'll
-+      keep things simple.
-+    */
-+
-+    if (server_version == nullptr)
-+      server_version = my_strdup(PSI_NOT_INSTRUMENTED,
-+                                 mysql_get_server_info(con), MYF(MY_WME));
-+  }
-+
-+  return server_version ? server_version : "";
-+}
-+
-+static int put_info(const char *str, INFO_TYPE info_type, uint error,
-+                    const char *sqlstate) {
-+  FILE *file = (info_type == INFO_ERROR ? stderr : stdout);
-+  static int inited = 0;
-+
-+  if (status.batch) {
-+    if (info_type == INFO_ERROR) {
-+      (void)fflush(stdout);  // flush stdout before stderr
-+      (void)fflush(file);
-+      fprintf(file, "ERROR");
-+      if (error) {
-+        if (sqlstate)
-+          (void)fprintf(file, " %d (%s)", error, sqlstate);
-+        else
-+          (void)fprintf(file, " %d", error);
-+      }
-+      if (status.query_start_line && line_numbers) {
-+        (void)fprintf(file, " at line %lu", status.query_start_line);
-+        if (status.file_name)
-+          (void)fprintf(file, " in file: '%s'", status.file_name);
-+      }
-+      (void)fprintf(file, ": %s\n", str);
-+      (void)fflush(file);
-+      if (!ignore_errors) return 1;
-+    } else if (info_type == INFO_RESULT && verbose > 1)
-+      tee_puts(str, file);
-+    if (unbuffered) fflush(file);
-+    return info_type == INFO_ERROR ? -1 : 0;
-+  }
-+  if (!opt_silent || info_type == INFO_ERROR) {
-+    if (!inited) {
-+      inited = 1;
-+    }
-+    if (info_type == INFO_ERROR) {
-+      if (!opt_nobeep) putchar('\a'); /* This should make a bell */
-+      if (error) {
-+        if (sqlstate)
-+          (void)tee_fprintf(file, "ERROR %d (%s): ", error, sqlstate);
-+        else
-+          (void)tee_fprintf(file, "ERROR %d: ", error);
-+      } else
-+        tee_puts("ERROR: ", file);
-+    }
-+    (void)tee_puts(str, file);
-+  }
-+  if (unbuffered) fflush(file);
-+  return info_type == INFO_ERROR ? -1 : 0;
-+}
-+
-+static int put_error(MYSQL *con) {
-+  return put_info(mysql_error(con), INFO_ERROR, mysql_errno(con),
-+                  mysql_sqlstate(con));
-+}
-+
-+/**
-+ Prints the SQL error, if any
-+
-+ Similar to @ref put_error, but prints the error only if there is any.
-+
-+ @param con the connection to check for errors
-+*/
-+static void put_error_if_any(MYSQL *con) {
-+  const char *err = mysql_error(con);
-+  if (err && *err)
-+    put_info(err, INFO_ERROR, mysql_errno(con), mysql_sqlstate(con));
-+}
-+
-+static void remove_cntrl(String *buffer) {
-+  const char *start = buffer->ptr();
-+  const char *end = start + buffer->length();
-+  while (start < end && !my_isgraph(charset_info, end[-1])) end--;
-+  buffer->length((uint)(end - start));
-+}
-+
-+/**
-+  Write data to a stream.
-+  Various modes, corresponding to --tab, --xml, --raw parameters,
-+  are supported.
-+
-+  @param file   Stream to write to
-+  @param s      String to write
-+  @param slen   String length
-+  @param flags  Flags for --tab, --xml, --raw.
-+*/
-+void tee_write(FILE *file, const char *s, size_t slen, int flags) {
-+#ifdef _WIN32
-+  bool is_console = my_win_is_console_cached(file);
-+#endif
-+  const char *se;
-+  for (se = s + slen; s < se; s++) {
-+    const char *t;
-+
-+    if (flags & MY_PRINT_MB) {
-+      int mblen;
-+      if (use_mb(charset_info) && (mblen = my_ismbchar(charset_info, s, se))) {
-+#ifdef _WIN32
-+        if (is_console)
-+          my_win_console_write(charset_info, s, mblen);
-+        else
-+#endif
-+            if (fwrite(s, 1, mblen, file) != (size_t)mblen) {
-+          perror("fwrite");
-+        }
-+        if (opt_outfile) {
-+          if (fwrite(s, 1, mblen, OUTFILE) != (size_t)mblen) {
-+            perror("fwrite");
-+          }
-+        }
-+        s += mblen - 1;
-+        continue;
-+      }
-+    }
-+
-+    if ((flags & MY_PRINT_XML) && (t = array_value(xmlmeta, *s)))
-+      tee_fputs(t, file);
-+    else if ((flags & MY_PRINT_SPS_0) && *s == '\0')
-+      tee_putc((int)' ', file);  // This makes everything hard
-+    else if ((flags & MY_PRINT_ESC_0) && *s == '\0')
-+      tee_fputs("\\0", file);  // This makes everything hard
-+    else if ((flags & MY_PRINT_CTRL) && *s == '\t')
-+      tee_fputs("\\t", file);  // This would destroy tab format
-+    else if ((flags & MY_PRINT_CTRL) && *s == '\n')
-+      tee_fputs("\\n", file);  // This too
-+    else if ((flags & MY_PRINT_CTRL) && *s == '\\')
-+      tee_fputs("\\\\", file);
-+    else {
-+#ifdef _WIN32
-+      if (is_console)
-+        my_win_console_putc(charset_info, (int)*s);
-+      else
-+#endif
-+        putc((int)*s, file);
-+      if (opt_outfile) putc((int)*s, OUTFILE);
-+    }
-+  }
-+}
-+
-+void tee_fprintf(FILE *file, const char *fmt, ...) {
-+  va_list args;
-+
-+  va_start(args, fmt);
-+#ifdef _WIN32
-+  if (my_win_is_console_cached(file))
-+    my_win_console_vfprintf(charset_info, fmt, args);
-+  else
-+#endif
-+    (void)vfprintf(file, fmt, args);
-+  va_end(args);
-+
-+  if (opt_outfile) {
-+    va_start(args, fmt);
-+    (void)vfprintf(OUTFILE, fmt, args);
-+    va_end(args);
-+  }
-+}
-+
-+/*
-+  Write a 0-terminated string to file and OUTFILE.
-+  TODO: possibly it's nice to have a version with length some day,
-+  e.g. tee_fnputs(s, slen, file),
-+  to print numerous ASCII constant strings among mysql.cc
-+  code, to avoid strlen(s) in my_win_console_fputs().
-+*/
-+void tee_fputs(const char *s, FILE *file) {
-+#ifdef _WIN32
-+  if (my_win_is_console_cached(file))
-+    my_win_console_fputs(charset_info, s);
-+  else
-+#endif
-+    fputs(s, file);
-+  if (opt_outfile) fputs(s, OUTFILE);
-+}
-+
-+void tee_puts(const char *s, FILE *file) {
-+  tee_fputs(s, file);
-+  tee_putc('\n', file);
-+}
-+
-+void tee_putc(int c, FILE *file) {
-+#ifdef _WIN32
-+  if (my_win_is_console_cached(file))
-+    my_win_console_putc(charset_info, c);
-+  else
-+#endif
-+    putc(c, file);
-+  if (opt_outfile) putc(c, OUTFILE);
-+}
-+
-+#if defined(_WIN32)
-+#include <time.h>
-+#else
-+#include <sys/times.h>
-+#ifdef _SC_CLK_TCK  // For mit-pthreads
-+#undef CLOCKS_PER_SEC
-+#define CLOCKS_PER_SEC (sysconf(_SC_CLK_TCK))
-+#endif
-+#endif
-+
-+static ulong start_timer(void) {
-+#if defined(_WIN32)
-+  return clock();
-+#else
-+  struct tms tms_tmp;
-+  return times(&tms_tmp);
-+#endif
-+}
-+
-+/**
-+  Write as many as 52+1 bytes to buff, in the form of a legible duration of
-+  time.
-+
-+  len("4294967296 days, 23 hours, 59 minutes, 60.00 seconds")  ->  52
-+*/
-+static void nice_time(double sec, char *buff, bool part_second) {
-+  ulong tmp;
-+  if (sec >= 3600.0 * 24) {
-+    tmp = (ulong)floor(sec / (3600.0 * 24));
-+    sec -= 3600.0 * 24 * tmp;
-+    buff = longlong10_to_str(tmp, buff, 10);
-+    buff = my_stpcpy(buff, tmp > 1 ? " days " : " day ");
-+  }
-+  if (sec >= 3600.0) {
-+    tmp = (ulong)floor(sec / 3600.0);
-+    sec -= 3600.0 * tmp;
-+    buff = longlong10_to_str(tmp, buff, 10);
-+    buff = my_stpcpy(buff, tmp > 1 ? " hours " : " hour ");
-+  }
-+  if (sec >= 60.0) {
-+    tmp = (ulong)floor(sec / 60.0);
-+    sec -= 60.0 * tmp;
-+    buff = longlong10_to_str(tmp, buff, 10);
-+    buff = my_stpcpy(buff, " min ");
-+  }
-+  if (part_second)
-+    sprintf(buff, "%.2f sec", sec);
-+  else
-+    sprintf(buff, "%d sec", (int)sec);
-+}
-+
-+static void end_timer(ulong start_time, char *buff) {
-+  nice_time((double)(start_timer() - start_time) / CLOCKS_PER_SEC, buff, true);
-+}
-+
-+static void mysql_end_timer(ulong start_time, char *buff) {
-+  buff[0] = ' ';
-+  buff[1] = '(';
-+  end_timer(start_time, buff + 2);
-+  my_stpcpy(strend(buff), ")");
-+}
-+
-+static const char *construct_prompt() {
-+  processed_prompt.mem_free();    // Erase the old prompt
-+  time_t lclock = time(nullptr);  // Get the date struct
-+  struct tm *t = localtime(&lclock);
-+
-+  /* parse thru the settings for the prompt */
-+  for (char *c = current_prompt; *c; c++) {
-+    if (*c != PROMPT_CHAR)
-+      processed_prompt.append(*c);
-+    else {
-+      switch (*++c) {
-+        case '\0':
-+          c--;  // stop it from going beyond if ends with %
-+          break;
-+        case 'c':
-+          add_int_to_prompt(++prompt_counter);
-+          break;
-+        case 'C':
-+          add_int_to_prompt(mysql_thread_id(&mysql));
-+          break;
-+        case 'v':
-+          if (connected)
-+            processed_prompt.append(mysql_get_server_info(&mysql));
-+          else
-+            processed_prompt.append("not_connected");
-+          break;
-+        case 'd':
-+          processed_prompt.append(current_db ? current_db : "(none)");
-+          break;
-+        case 'h': {
-+          const char *prompt;
-+          prompt = connected ? mysql_get_host_info(&mysql) : "not_connected";
-+          if (strstr(prompt, "Localhost"))
-+            processed_prompt.append("localhost");
-+          else {
-+            const char *end = strcend(prompt, ' ');
-+            processed_prompt.append(prompt, (uint)(end - prompt));
-+          }
-+          break;
-+        }
-+        case 'p': {
-+          if (!connected) {
-+            processed_prompt.append("not_connected");
-+            break;
-+          }
-+
-+          const char *host_info = mysql_get_host_info(&mysql);
-+          if (strstr(host_info, "memory")) {
-+            processed_prompt.append(mysql.host);
-+          } else if (strstr(host_info, "TCP/IP") || !mysql.unix_socket)
-+            add_int_to_prompt(mysql.port);
-+          else {
-+            char *pos = strrchr(mysql.unix_socket, '/');
-+            processed_prompt.append(pos ? pos + 1 : mysql.unix_socket);
-+          }
-+        } break;
-+        case 'U':
-+          if (!full_username) init_username();
-+          processed_prompt.append(
-+              full_username ? full_username
-+                            : (current_user ? current_user : "(unknown)"));
-+          break;
-+        case 'u':
-+          if (!full_username) init_username();
-+          processed_prompt.append(
-+              part_username ? part_username
-+                            : (current_user ? current_user : "(unknown)"));
-+          break;
-+        case PROMPT_CHAR:
-+          processed_prompt.append(PROMPT_CHAR);
-+          break;
-+        case 'n':
-+          processed_prompt.append('\n');
-+          break;
-+        case ' ':
-+        case '_':
-+          processed_prompt.append(' ');
-+          break;
-+        case 'R':
-+          if (t->tm_hour < 10) processed_prompt.append('0');
-+          add_int_to_prompt(t->tm_hour);
-+          break;
-+        case 'r':
-+          int getHour;
-+          getHour = t->tm_hour % 12;
-+          if (getHour == 0) getHour = 12;
-+          if (getHour < 10) processed_prompt.append('0');
-+          add_int_to_prompt(getHour);
-+          break;
-+        case 'm':
-+          if (t->tm_min < 10) processed_prompt.append('0');
-+          add_int_to_prompt(t->tm_min);
-+          break;
-+        case 'y':
-+          int getYear;
-+          getYear = t->tm_year % 100;
-+          if (getYear < 10) processed_prompt.append('0');
-+          add_int_to_prompt(getYear);
-+          break;
-+        case 'Y':
-+          add_int_to_prompt(t->tm_year + 1900);
-+          break;
-+        case 'D':
-+          char *dateTime;
-+          dateTime = ctime(&lclock);
-+          processed_prompt.append(strtok(dateTime, "\n"));
-+          break;
-+        case 's':
-+          if (t->tm_sec < 10) processed_prompt.append('0');
-+          add_int_to_prompt(t->tm_sec);
-+          break;
-+        case 'w':
-+          processed_prompt.append(day_names[t->tm_wday]);
-+          break;
-+        case 'P':
-+          processed_prompt.append(t->tm_hour < 12 ? "am" : "pm");
-+          break;
-+        case 'o':
-+          add_int_to_prompt(t->tm_mon + 1);
-+          break;
-+        case 'O':
-+          processed_prompt.append(month_names[t->tm_mon]);
-+          break;
-+        case '\'':
-+          processed_prompt.append("'");
-+          break;
-+        case '"':
-+          processed_prompt.append('"');
-+          break;
-+        case 'S':
-+          processed_prompt.append(';');
-+          break;
-+        case 't':
-+          processed_prompt.append('\t');
-+          break;
-+        case 'l':
-+          processed_prompt.append(delimiter_str);
-+          break;
-+        case 'T':
-+          if (mysql.server_status & SERVER_STATUS_IN_TRANS)
-+            processed_prompt.append("*");
-+          break;
-+        default:
-+          processed_prompt.append(c);
-+      }
-+    }
-+  }
-+  processed_prompt.append('\0');
-+  return processed_prompt.ptr();
-+}
-+
-+static void add_int_to_prompt(int toadd) {
-+  processed_prompt.append_longlong(toadd);
-+}
-+
-+static void init_username() {
-+  my_free(full_username);
-+  my_free(part_username);
-+
-+  MYSQL_RES *result = nullptr;
-+  if (!mysql_query(&mysql, "select USER()") &&
-+      (result = mysql_use_result(&mysql))) {
-+    MYSQL_ROW cur = mysql_fetch_row(result);
-+    full_username = my_strdup(PSI_NOT_INSTRUMENTED, cur[0], MYF(MY_WME));
-+    part_username =
-+        my_strdup(PSI_NOT_INSTRUMENTED, strtok(cur[0], "@"), MYF(MY_WME));
-+    (void)mysql_fetch_row(result);  // Read eof
-+  }
-+}
-+
-+// Get the current OS user name.
-+static void get_current_os_user() {
-+  const char *user;
-+
-+#ifdef _WIN32
-+  char buf[255];
-+  WCHAR wbuf[255];
-+  DWORD wbuf_len = sizeof(wbuf) / sizeof(WCHAR);
-+  size_t len;
-+  uint dummy_errors;
-+
-+  if (GetUserNameW(wbuf, &wbuf_len)) {
-+    len = my_convert(buf, sizeof(buf) - 1, charset_info, (char *)wbuf,
-+                     wbuf_len * sizeof(WCHAR), &my_charset_utf16le_bin,
-+                     &dummy_errors);
-+    buf[len] = 0;
-+    user = buf;
-+  } else {
-+    user = "UNKNOWN USER";
-+  }
-+#else
-+#ifdef HAVE_GETPWUID
-+  struct passwd *pw;
-+
-+  if ((pw = getpwuid(geteuid())) != nullptr)
-+    user = pw->pw_name;
-+  else
-+#endif
-+      if (!(user = getenv("USER")) && !(user = getenv("LOGNAME")) &&
-+          !(user = getenv("LOGIN")))
-+    user = "UNKNOWN USER";
-+#endif /* _WIN32 */
-+  current_os_user = my_strdup(PSI_NOT_INSTRUMENTED, user, MYF(MY_WME));
-+  return;
-+}
-+
-+// Get the current OS sudo user name (only for non-Windows platforms).
-+static void get_current_os_sudouser() {
-+#ifndef _WIN32
-+  if (getenv("SUDO_USER"))
-+    current_os_sudouser =
-+        my_strdup(PSI_NOT_INSTRUMENTED, getenv("SUDO_USER"), MYF(MY_WME));
-+#endif /* !_WIN32 */
-+  return;
-+}
-+
-+static int com_prompt(String *buffer [[maybe_unused]], char *line) {
-+  char *ptr = strchr(line, ' ');
-+  prompt_counter = 0;
-+  my_free(current_prompt);
-+  current_prompt = my_strdup(PSI_NOT_INSTRUMENTED,
-+                             ptr ? ptr + 1 : default_prompt, MYF(MY_WME));
-+  if (!ptr)
-+    tee_fprintf(stdout, "Returning to default PROMPT of %s\n", default_prompt);
-+  else
-+    tee_fprintf(stdout, "PROMPT set to '%s'\n", current_prompt);
-+  return 0;
-+}
-+
-+static int com_resetconnection(String *buffer [[maybe_unused]],
-+                               char *line [[maybe_unused]]) {
-+  int error;
-+  global_attrs->clear(connected ? &mysql : nullptr);
-+  error = mysql_reset_connection(&mysql);
-+  if (error) {
-+    if (status.batch) return 0;
-+    return put_error(&mysql);
-+  }
-+  return error;
-+}